程序员面试金典(第 6 版)
- 面试题 01.01. 判定字符是否唯一
- 面试题 01.02. 判定是否互为字符重排
- 面试题 01.03. URL化
- 面试题 01.04. 回文排列
- 面试题 01.05. 一次编辑
- 面试题 01.06. 字符串压缩
- 面试题 01.07. 旋转矩阵
- 面试题 01.08. 零矩阵
- 面试题 01.09. 字符串轮转
- 面试题 02.01. 移除重复节点
- 面试题 02.02. 返回倒数第 k 个节点
- 面试题 02.03. 删除中间节点
- 面试题 02.04. 分割链表
- 面试题 02.05. 链表求和
- 面试题 02.06. 回文链表
- 面试题 02.07. 链表相交
- 面试题 02.08. 环路检测
- 面试题 03.01. 三合一
- 面试题 03.02. 栈的最小值
- 面试题 03.03. 堆盘子
- 面试题 03.04. 化栈为队
- 面试题 03.05. 栈排序
- 面试题 03.06. 动物收容所
- 面试题 04.01. 节点间通路
- 面试题 04.02. 最小高度树
- 面试题 04.03. 特定深度节点链表
- 面试题 04.04. 检查平衡性
- 面试题 04.05. 合法二叉搜索树
- 面试题 04.06. 后继者
- 面试题 04.08. 首个共同祖先
- 面试题 04.09. 二叉搜索树序列
- 面试题 04.10. 检查子树
- 面试题 04.12. 求和路径
- 面试题 05.01. 插入
- 面试题 05.03. 翻转数位
- 面试题 05.04. 下一个数
- 面试题 05.06. 整数转换
- 面试题 05.07. 配对交换
- 面试题 08.01. 三步问题
- 面试题 08.02. 迷路的机器人
- 面试题 08.03. 魔术索引
- 面试题 08.04. 幂集
- 面试题 08.06. 汉诺塔问题
- 面试题 08.07. 无重复字符串的排列组合
- 面试题 08.08. 有重复字符串的排列组合
- 面试题 08.09. 括号
- 面试题 08.10. 颜色填充
- 面试题 08.11. 硬币
- 面试题 08.12. 八皇后
- 面试题 08.13. 堆箱子
- 面试题 10.01. 合并排序的数组
- 面试题 10.02. 变位词组
- 面试题 10.03. 搜索旋转数组
- 面试题 10.05. 稀疏数组搜索
- 面试题 10.09. 排序矩阵查找
- 面试题 10.11. 峰与谷
- 面试题 16.01. 交换数字
- 面试题 16.02. 单词频率
- 面试题 16.04. 井字游戏
- 面试题 16.05. 阶乘尾数
- 面试题 16.06. 最小差
- 面试题 16.07. 最大数值
- 面试题 16.08. 整数的英语表示
- 面试题 16.10. 生存人数
- 面试题 16.11. 跳水板
- 面试题 16.14. 最佳直线
- 面试题 16.15. 珠玑妙算
- 面试题 16.16. 部分排序
- 面试题 16.17. 连续数列
- 面试题 16.19. 水域大小
- 面试题 16.20. T9键盘
- 面试题 16.21. 交换和
- 面试题 16.22. 兰顿蚂蚁
- 面试题 16.24. 数对和
- 面试题 16.25. LRU 缓存
- 面试题 16.26. 计算器
- 面试题 17.04. 消失的数字
- 面试题 17.05. 字母与数字
- 面试题 17.06. 2出现的次数
- 面试题 17.08. 马戏团人塔
- 面试题 17.09. 第 k 个数
- 面试题 17.10. 主要元素
- 面试题 17.11. 单词距离
- 面试题 17.12. BiNode
- 面试题 17.13. 恢复空格
- 面试题 17.14. 最小K个数
- 面试题 17.15. 最长单词
- 面试题 17.16. 按摩师
- 面试题 17.18. 最短超串
- 面试题 17.19. 消失的两个数字
- 面试题 17.20. 连续中值
- 面试题 17.21. 直方图的水量
- 面试题 17.22. 单词转换
- 面试题 17.23. 最大黑方阵
- 面试题 17.24. 最大子矩阵
- 面试题 17.26. 稀疏相似度
- 面试题19. 正则表达式匹配
- 面试题32 - I. 从上到下打印二叉树
面试题 01.01. 判定字符是否唯一
class Solution {
public boolean isUnique(String astr) {
if (astr == null || astr.length() <= 1) return true;
boolean[] map = new boolean[26];
for (char ch : astr.toCharArray()) {
if (map[ch - 'a']) return false;
map[ch - 'a'] = true;
}
return true;
}
}
面试题 01.02. 判定是否互为字符重排
class Solution {
public boolean CheckPermutation(String s1, String s2) {
if (s1 == null && s2 == null) return true;
if (s1 == null || s2 == null || s1.length() != s2.length()) return false;
int[] map = new int[26];
for (char ch : s1.toCharArray()) {
++map[ch - 'a'];
}
for (char ch : s2.toCharArray()) {
if (map[ch - 'a'] == 0) return false;
--map[ch - 'a'];
}
return true;
}
}
面试题 01.03. URL化
class Solution {
public String replaceSpaces(String S, int length) {
if (S == null || S.length() == 0) return S;
int num = 0;
for (int i = 0; i < length; i++) {
if (S.charAt(i) == ' ') {
num++;
}
}
char[] arr = new char[length + num * 2];
int last = arr.length - 1, pre = length - 1;
while (last >= 0) {
if (S.charAt(pre) != ' ') arr[last--] = S.charAt(pre--);
else {
arr[last--] = '0';
arr[last--] = '2';
arr[last--] = '%';
--pre;
}
}
return new String(arr);
}
}
面试题 01.04. 回文排列
class Solution {
public boolean canPermutePalindrome(String s) {
if (s == null || s.length() <= 1) return true;
boolean[] map = new boolean[256];
for (char ch : s.toCharArray()) {
map[ch] ^= true;
}
boolean flag = false;
for (boolean b : map) {
if (b) {
if (flag) return false;
flag = true;
}
}
return true;
}
}
面试题 01.05. 一次编辑
- oneEditAway(“teacher”,“lbeacher”)
class Solution {
public boolean oneEditAway(String first, String second) {
if (first.length() == 0 || second.length() == 0) return true;
int subLen = first.length() - second.length();
if (Math.abs(subLen) > 1) return false;
int i = first.length() - 1, j = second.length() - 1;
boolean flag = false;
while (i >= 0 && j >= 0) {
if (first.charAt(i) != second.charAt(j)) {
if (subLen == -1) i++;
else if (subLen == 1) j++;
if (flag) return false;
flag = true;
}
i--;
j--;
}
return true;
}
}
面试题 01.06. 字符串压缩
class Solution {
public String compressString(String S) {
if (S == null || S.length() <= 1) return S;
StringBuffer res = new StringBuffer();
char[] arr = S.toCharArray();
int pre = 0, N = arr.length;
for (int i = 1; i < N; i++) {
if (arr[i] != arr[i - 1]) {
res.append(arr[i - 1]);
res.append(i - pre);
pre = i;
}
}
res.append(arr[N - 1]);
res.append(N - pre);
return res.length() >= N ? S : res.toString();
}
}
面试题 01.07. 旋转矩阵
class Solution {
public void rotate(int[][] matrix) {
if (matrix.length <= 1) return;
int firstRow = 0, firstLine = 0, secondRow = matrix.length - 1, secondLine = matrix[0].length - 1;
while (firstLine < secondLine && firstRow < secondRow) {
circleSway(matrix, firstRow++, firstLine++, secondRow--, secondLine--);
}
for (int[] a : matrix) System.out.println(Arrays.toString(a));
}
private void circleSway(int[][] matrix, int locR1, int locL1, int locR2, int locL2) {
for (int i = 0; i < locL2 - locL1; i++) {
int temp = matrix[locR1][locL1 + i];
matrix[locR1][locL1 + i] = matrix[locR2 - i][locL1];
matrix[locR2 - i][locL1] = matrix[locR2][locL2 - i];
matrix[locR2][locL2 - i] = matrix[locR1 + i][locL2];
matrix[locR1 + i][locL2] = temp;
}
}
}
面试题 01.08. 零矩阵
class Solution {
public void setZeroes(int[][] matrix) {
if (matrix == null) return;
int M = matrix.length, N = matrix[0].length;
boolean[] rows = new boolean[M], lines = new boolean[N];
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
if (matrix[i][j] == 0) {
rows[i] = true;
lines[j] = true;
}
}
}
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
if (rows[i] || lines[j]) {
matrix[i][j] = 0;
}
}
}
}
}
面试题 01.09. 字符串轮转
class Solution {
public boolean isFlipedString(String s1, String s2) {
if (s1 == null && s2 == null) return true;
if (s1 == null || s2 == null) return false;
if (s1.length() != s2.length()) return false;
String s = s1 + s1;
return s.contains(s2);
}
}
面试题 02.01. 移除重复节点
class Solution {
public ListNode removeDuplicateNodes(ListNode head) {
if (head == null || head.next == null) return head;
BitSet set = new BitSet();
ListNode tail = head;
set.set(head.val, true);
while (tail.next != null) {
if (!set.get(tail.next.val)) {
set.set(tail.next.val, true);
tail = tail.next;
} else {
tail.next = tail.next.next;
}
}
return head;
}
}
面试题 02.02. 返回倒数第 k 个节点
class Solution {
public int kthToLast(ListNode head, int k) {
ListNode tail = head;
for (int i = 0; i < k; i++) {
tail = tail.next;
}
ListNode res = head;
while (tail != null) {
tail = tail.next;
res = res.next;
}
return res.val;
}
}
面试题 02.03. 删除中间节点
class Solution {
public void deleteNode(ListNode node) {
node.val=node.next.val;
node.next=node.next.next;
}
}
面试题 02.04. 分割链表
class Solution {
public ListNode partition(ListNode head, int x) {
if (head == null || head.next == null) return head;
ListNode small = new ListNode(), fast = new ListNode();
small.next = head;
ListNode smallTail = small, fastTail = fast;
while (smallTail.next != null) {
if (smallTail.next.val >= x) {
fastTail.next = smallTail.next;
fastTail=fastTail.next;
smallTail.next = smallTail.next.next;
fastTail.next=null;
}else {
smallTail=smallTail.next;
}
}
smallTail.next = fast.next;
return small.next;
}
}
面试题 02.05. 链表求和
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
if (l1 == null || l2 == null) return l1 == null ? l2 : l1;
ListNode tail1 = l1, tail2 = l2;
int pre = 0;
if (l1.val + l2.val >= 10) {
l1.val = l1.val + l2.val - 10;
pre = 1;
} else {
l1.val = l1.val + l2.val;
}
while (tail1.next != null && tail2.next != null) {
if (tail1.next.val + tail2.next.val + pre >= 10) {
tail1.next.val = tail1.next.val + tail2.next.val + pre - 10;
pre = 1;
} else {
tail1.next.val = tail1.next.val + tail2.next.val + pre;
pre = 0;
}
tail1 = tail1.next;
tail2 = tail2.next;
}
if (tail2.next != null) tail1.next = tail2.next;
if (pre == 0) return l1;
while (tail1.next != null && pre == 1) {
if (tail1.next.val + pre >= 10) {
tail1.next.val = 0;
pre = 1;
} else {
tail1.next.val++;
pre = 0;
}
tail1 = tail1.next;
}
if (tail1.next == null && pre == 1) {
tail1.next = new ListNode(1);
}
return l1;
}
}
面试题 02.06. 回文链表
class Solution {
public boolean isPalindrome(ListNode head) {
if (head == null || head.next == null) return true;
ListNode fastNode = head;
ListNode slowNode = head;
while (fastNode.next != null && fastNode.next.next != null) {
fastNode = fastNode.next.next;
slowNode = slowNode.next;
}
slowNode = slowNode.next;
fastNode = null;
while (slowNode != null) {
ListNode nextnode = slowNode.next;
slowNode.next = fastNode;
fastNode = slowNode;
slowNode = nextnode;
}
while (fastNode != null) {
if (head.val != fastNode.val) return false;
fastNode = fastNode.next;
head = head.next;
}
return true;
}
}
面试题 02.07. 链表相交
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) return null;
int N = 0;
ListNode tail = headA,pre;
while (tail.next != null) {
N++;
tail = tail.next;
}
tail = headB;
while (tail.next != null) {
N--;
tail = tail.next;
}
if (N < 0) {
pre = headB;
tail = headA;
N = -N;
} else {
pre = headA;
tail = headB;
}
while (N-- > 0) pre = pre.next;
while (pre != tail) {
pre = pre.next;
tail = tail.next;
}
return pre;
}
}
面试题 02.08. 环路检测
class Solution {
public ListNode detectCycle(ListNode head) {
if (head == null) return null;
ListNode slow = head;
ListNode quick = head;
boolean flag = false;
while (quick.next != null && quick.next.next != null) {
slow = slow.next;
quick = quick.next.next;
if (slow == quick) {
flag = true;
break;
}
}
if (!flag) return null;
quick = head;
while (quick != slow) {
quick = quick.next;
slow = slow.next;
}
return slow;
}
}
面试题 03.01. 三合一
class TripleInOne {
private int[] arr = {};
private int[] size = {};
private int stackSize;
public TripleInOne(int stackSize) {
this.stackSize = stackSize;
arr = new int[3*stackSize];
size = new int[] {0, 0, 0};
}
public void push(int stackNum, int value) {
int length = size[stackNum];
if (length < stackSize) {
arr[stackNum*stackSize+length] = value;
size[stackNum] = length + 1;
}
}
public int pop(int stackNum) {
int topVal = peek(stackNum);
if (size[stackNum] > 0)
size[stackNum] -= 1;
return topVal;
}
public int peek(int stackNum) {
if (size[stackNum] == 0)
return -1;
return arr[stackNum*stackSize+size[stackNum]-1];
}
public boolean isEmpty(int stackNum) {
return size[stackNum] == 0;
}
}
面试题 03.02. 栈的最小值
public class MinStack {
private Stack<Integer> data;
private Stack<Integer> helper;
public MinStack() {
data = new Stack<>();
helper = new Stack<>();
}
public void push(int x) {
data.add(x);
if (helper.isEmpty() || helper.peek() >= x) {
helper.add(x);
}
}
public void pop() {
if (!data.isEmpty()) {
int top = data.pop();
if(top == helper.peek()){
helper.pop();
}
}
}
public int top() {
if(!data.isEmpty()){
return data.peek();
}
throw new RuntimeException("栈中元素为空,此操作非法");
}
public int getMin() {
if(!helper.isEmpty()){
return helper.peek();
}
throw new RuntimeException("栈中元素为空,此操作非法");
}
}
面试题 03.03. 堆盘子
class StackOfPlates {
private List<Stack<Integer>> stackList;
private int cap;
public StackOfPlates(int cap) {
stackList = new ArrayList<>();
this.cap = cap;
}
public void push(int val) {
if (cap <= 0) return;
if (stackList.isEmpty() || stackList.get(stackList.size() - 1).size() == cap) {
Stack<Integer> stack = new Stack<>();
stack.push(val);
stackList.add(stack);
return;
}
stackList.get(stackList.size() - 1).push(val);
}
public int pop() {
return popAt(stackList.size() - 1);
}
public int popAt(int index) {
if (index < 0 || index >= stackList.size()) return -1;
Stack<Integer> stack = stackList.get(index);
int res = stack.pop();
if (stack.isEmpty()) stackList.remove(index);
return res;
}
}
面试题 03.04. 化栈为队
class MyQueue {
Stack<Integer> addStack = new Stack<>();
Stack<Integer> delStack = new Stack<>();
public MyQueue() {
}
public void push(int x) {
addStack.push(x);
}
public int pop() {
if (!delStack.isEmpty()) return delStack.pop();
if (addStack.isEmpty()) return -1;
while (!addStack.isEmpty()) delStack.add(addStack.pop());
return delStack.pop();
}
public int peek() {
if (!delStack.isEmpty()) return delStack.peek();
if (addStack.isEmpty()) return -1;
while (!addStack.isEmpty()) delStack.add(addStack.pop());
return delStack.peek();
}
public boolean empty() {
return ( addStack.isEmpty() && delStack.isEmpty() );
}
}
面试题 03.05. 栈排序
class SortedStack {
Deque<Integer> minStack = new LinkedList<>();
Deque<Integer> tempStack = new LinkedList<>();
public SortedStack() {
}
public void push(int val) {
while (!minStack.isEmpty() && minStack.peek() < val) tempStack.push(minStack.pop());
minStack.push(val);
while (!tempStack.isEmpty()) minStack.push(tempStack.pop());
}
public void pop() {
if (!isEmpty()) minStack.pop();
}
public int peek() {
return minStack.isEmpty() ? -1 : minStack.peek();
}
public boolean isEmpty() {
return minStack.isEmpty();
}
}
面试题 03.06. 动物收容所
class AnimalShelf {
Deque<int[]> cat;
Deque<int[]> dog;
public AnimalShelf() {
cat = new ArrayDeque<>();
dog = new ArrayDeque<>();
}
public void enqueue(int[] animal) {
if(animal[1] == 0) cat.add(animal);
else dog.add(animal);
}
public int[] dequeueAny() {
if(cat.isEmpty() && dog.isEmpty()) return new int[]{-1,-1};
if(cat.isEmpty()) return dog.poll();
if(dog.isEmpty()) return cat.poll();
if(cat.peek()[0] < dog.peek()[0]) return cat.poll();
return dog.poll();
}
public int[] dequeueDog() {
if(dog.isEmpty()) return new int[]{-1,-1};
return dog.poll();
}
public int[] dequeueCat() {
if(cat.isEmpty()) return new int[]{-1,-1};
return cat.poll();
}
}
面试题 04.01. 节点间通路
class Solution {
public boolean findWhetherExistsPath(int n, int[][] graph, int start, int target) {
if (graph == null || graph.length == 0) return false;
ArrayList<LinkedList<Integer>> list = new ArrayList<>(n);
for (int i = 0; i < n; i++) {
list.add(new LinkedList<>());
}
for (int[] val : graph) {
list.get(val[0]).add(val[1]);
}
boolean[] isvisited = new boolean[n];
Queue<Integer> queue = new LinkedList<>();
queue.add(start);
isvisited[start] = true;
while (!queue.isEmpty()) {
int x = queue.poll();
if (x == target) return true;
for (int next : list.get(x)) {
if (!isvisited[next]) {
queue.add(next);
isvisited[next] = true;
}
}
}
return false;
}
}
面试题 04.02. 最小高度树
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
if (nums == null || nums.length == 0) return null;
return process(nums, 0, nums.length - 1);
}
private TreeNode process(int[] nums, int left, int right) {
if (left > right) return null;
int mid = (left + right) / 2;
TreeNode x = new TreeNode(nums[mid]);
x.left = process(nums, left, mid - 1);
x.right = process(nums, mid + 1, right);
return x;
}
}
面试题 04.03. 特定深度节点链表
class Solution {
public ListNode[] listOfDepth(TreeNode tree) {
if (tree == null) return null;
Queue<TreeNode> queue = new LinkedList<>();
ArrayList<ListNode> res = new ArrayList<>();
res.add(new ListNode(tree.val));
ListNode head = new ListNode();
ListNode tail = head;
TreeNode thisLast = tree, nextLast = null;
queue.add(tree);
while (!queue.isEmpty()) {
TreeNode x = queue.poll();
if (x.left != null) {
queue.add(x.left);
tail.next = new ListNode(x.left.val);
tail = tail.next;
nextLast = x.left;
}
if (x.right != null) {
queue.add(x.right);
tail.next = new ListNode(x.right.val);
tail = tail.next;
nextLast = x.right;
}
if (x == thisLast) {
if (head.next!=null)res.add(head.next);
head = new ListNode();
tail = head;
thisLast = nextLast;
nextLast = null;
}
}
return res.toArray(new ListNode[0]);
}
}
面试题 04.04. 检查平衡性
class Solution {
public boolean isBalanced(TreeNode root) {
if (root == null) return true;
return process(root).is;
}
public transData process(TreeNode x) {
if (x == null) return new transData(0, true);
transData l = process(x.left), r = process(x.right);
if (!l.is || !r.is || Math.abs(l.height - r.height) > 1) return new transData(-1, false);
return new transData(Math.max(l.height, r.height) + 1, true);
}
static class transData {
int height;
boolean is;
public transData(int _height, boolean _is) {
height = _height;
is = _is;
}
}
}
面试题 04.05. 合法二叉搜索树
class Solution {
public boolean isValidBST(TreeNode root) {
return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
private boolean isValidBST(TreeNode root, long min, long max) {
return root == null ||
(root.val > min && root.val < max &&
isValidBST(root.left, min, root.val) &&
isValidBST(root.right, root.val, max));
}
}
面试题 04.06. 后继者
class Solution {
public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
if (root == null) {
return null;
}
if (p.val >= root.val) {
return inorderSuccessor(root.right, p);
}
TreeNode node = inorderSuccessor(root.left, p);
return node == null ? root : node;
}
}
面试题 04.08. 首个共同祖先
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || root == p || root == q) return root;
TreeNode l = lowestCommonAncestor(root.left, p, q);
TreeNode r = lowestCommonAncestor(root.right, p, q);
if (l != null && r != null) return root;
return l == null ? r : l;
}
}
面试题 04.09. 二叉搜索树序列
class Solution {
List<List<Integer>> res = new LinkedList<>();
public List<List<Integer>> BSTSequences(TreeNode root) {
if (root == null) {
res.add(new LinkedList<>());
return res;
}
LinkedList<Integer> path = new LinkedList<>();
path.add(root.val);
helper(root, new LinkedList<>(), path);
return res;
}
public void helper(TreeNode root, LinkedList<TreeNode> queue, LinkedList<Integer> path) {
if (root == null) return;
if (root.left != null) queue.add(root.left);
if (root.right != null) queue.add(root.right);
if (queue.isEmpty()) {
res.add(new LinkedList<>(path));
return;
}
int lens = queue.size();
for (int i = 0; i < lens; i++) {
TreeNode cur = queue.get(i);
queue.remove(i);
path.add(cur.val);
helper(cur, new LinkedList<>(queue), path);
queue.add(i, cur);
path.removeLast();
}
}
}
面试题 04.10. 检查子树
class Solution {
public boolean checkSubTree(TreeNode t1, TreeNode t2) {
if (t2 == null) return true;
if (t1 == null) return false;
boolean flag = false;
if (t1.val == t2.val) flag = helperCompareTree(t1, t2);
if (!flag) flag = checkSubTree(t1.left, t2);
if (!flag) flag = checkSubTree(t1.right, t2);
return flag;
}
private boolean helperCompareTree(TreeNode t1, TreeNode t2) {
if (t2 == null) return true;
if (t1 == null) return false;
if (t1.val != t2.val) return false;
return helperCompareTree(t1.left, t2.left) && helperCompareTree(t1.right, t2.right);
}
}
面试题 04.12. 求和路径
class Solution {
public int pathSum(TreeNode root, int sum) {
Map<Integer, Integer> map = new HashMap<>();
map.put(0, 1);
return helper(root, map, sum, 0);
}
private int helper(TreeNode node, Map<Integer, Integer> prefixSum, int sum, int curSum) {
if (node == null) {
return 0;
}
curSum += node.val;
int count = prefixSum.getOrDefault(curSum - sum, 0);
prefixSum.put(curSum, prefixSum.getOrDefault(curSum, 0) + 1);
count += helper(node.left, prefixSum, sum, curSum);
count += helper(node.right, prefixSum, sum, curSum);
prefixSum.put(curSum, prefixSum.getOrDefault(curSum, 0) - 1);
return count;
}
}
面试题 05.01. 插入
class Solution {
public int insertBits(int N, int M, int i, int j) {
int k = 1 << i;
M <<= i;
while (i++ <= j) {
N &= ~k;
k <<= 1;
}
return M|N;
}
}
面试题 05.03. 翻转数位
class Solution {
public int reverseBits(int num) {
int maxLen = 0, preLen = 0, curLen = 0, bits = 32;
while (bits-- > 0) {
if ((num & 1) == 0) {
curLen -= preLen;
preLen = curLen + 1;
}
curLen++;
maxLen = Math.max(maxLen, curLen);
num >>= 1;
}
return maxLen;
}
}
面试题 05.04. 下一个数
class Solution {
public int[] findClosedNumbers(int num) {
if (num == 1) return new int[]{2, -1};
if (num == 2147483647) return new int[]{-1, -1};
int MAX = nextMax(num);
int MIN = ~nextMax(~num);
if (MAX < 0) MAX = -1;
return new int[]{MAX, MIN};
}
int nextMax(int num) {
int x = num & -num;
int y = x + num;
return ((num & ~y) / x >> 1 | y);
}
}
面试题 05.06. 整数转换
class Solution {
public int convertInteger(int A, int B) {
int C = A ^ B, res = 0;
while (C != 0) {
C &= (C - 1);
++res;
}
return res;
}
}
面试题 05.07. 配对交换
class Solution {
public int exchangeBits(int num) {
return (num & 0x55555555) << 1 | (num & 0xAAAAAAAA) >> 1;
}
}
面试题 08.01. 三步问题
class Solution {
public int waysToStep(int n) {
if (n == 1) return 1;
if (n == 2) return 2;
if (n == 3) return 4;
long a = 1, b = 1, c = 2, d = 0;
for (int i = n - 3; i >= 0; i--) {
d =( a + b + c) % 1000000007;
a = b;
b = c;
c = d;
}
return (int) (d % 1000000007);
}
}
面试题 08.02. 迷路的机器人
class Solution {
LinkedList<List<Integer>> res = new LinkedList<>();
boolean[][] isvisited;
int M, N;
public List<List<Integer>> pathWithObstacles(int[][] obstacleGrid) {
M = obstacleGrid.length;
N = obstacleGrid[0].length;
isvisited = new boolean[M][N];
dfs(obstacleGrid, 0, 0);
return res;
}
private boolean dfs(int[][] obstacleGrid, int i, int j) {
if (i < 0 || i >= M || j < 0 || j >= N || obstacleGrid[i][j] == 1 || isvisited[i][j]) return false;
res.addLast(Arrays.asList(i, j));
if (i == M - 1 && j == N - 1) return true;
isvisited[i][j] = true;
if (dfs(obstacleGrid, i + 1, j)) return true;
if (dfs(obstacleGrid, i, j + 1)) return true;
res.removeLast();
return false;
}
}
面试题 08.03. 魔术索引
class Solution {
public int findMagicIndex(int[] nums) {
for(int i=0;i<nums.length; ){
if(nums[i]==i)
return i;
i=Math.max(nums[i],i+1);
}
return -1;
}
}
面试题 08.04. 幂集
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> subsets(int[] nums) {
if (nums == null || nums.length == 0) return res;
backtrack(0, nums);
return res;
}
private void backtrack(int index, int[] nums) {
res.add(new ArrayList<>(path));
for (int i = index; i < nums.length; i++) {
path.addLast(nums[i]);
backtrack(i + 1, nums);
path.removeLast();
}
}
}
面试题 08.06. 汉诺塔问题
class Solution {
public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {
int n = A.size();
move(n, A, B, C);
}
void move(int n, List<Integer> A, List<Integer> B, List<Integer> C) {
if (n == 1) {
C.add(A.remove(A.size() - 1));
return;
}
move(n - 1, A, C, B);
C.add(A.remove(A.size() - 1));
move(n - 1, B, A, C);
}
}
面试题 08.07. 无重复字符串的排列组合
class Solution {
ArrayList<String> res = new ArrayList<>();
StringBuffer sb = new StringBuffer();
char[] arr;
boolean[] isvisited;
public String[] permutation(String S) {
if (S == null || S.length() == 0) return res.toArray(new String[0]);
isvisited = new boolean[S.length()];
arr = S.toCharArray();
backtrack(0);
return res.toArray(new String[0]);
}
private void backtrack(int i) {
if (i == arr.length) {
res.add(sb.toString());
return;
}
for (int n = 0; n < arr.length; n++) {
if (!isvisited[n]) {
isvisited[n] = true;
sb.append(arr[n]);
backtrack(i + 1);
isvisited[n] = false;
sb.deleteCharAt(sb.length() - 1);
}
}
}
}
面试题 08.08. 有重复字符串的排列组合
class Solution {
ArrayList<String> res = new ArrayList<>();
StringBuffer sb = new StringBuffer();
char[] arr;
boolean[] isvisited;
public String[] permutation(String S) {
if (S == null || S.length() == 0) return res.toArray(new String[0]);
isvisited = new boolean[S.length()];
arr = S.toCharArray();
Arrays.sort(arr);
backtrack(0);
return res.toArray(new String[0]);
}
private void backtrack(int i) {
if (sb.length() == arr.length) {
res.add(sb.toString());
return;
}
for (int n = 0; n < arr.length; n++) {
if (n > 0 && arr[n] == arr[n - 1] && !isvisited[n - 1]) continue;
if (!isvisited[n]) {
isvisited[n] = true;
sb.append(arr[n]);
backtrack(i + 1);
isvisited[n] = false;
sb.deleteCharAt(sb.length() - 1);
}
}
}
}
面试题 08.09. 括号
class Solution {
List<String> list = new ArrayList<String>();
int N;
StringBuffer s = new StringBuffer("");
public List<String> generateParenthesis(int n) {
N = n;
process(0, 0);
return list;
}
private void process(int i, int j) {
if (j == N) {
list.add(s.toString());
return;
}
if (i < N) {
s.append("(");
process(i + 1, j);
s.deleteCharAt(i + j);
}
if (j < i) {
s.append(")");
process(i, j + 1);
s.deleteCharAt(i + j);
}
}
}
面试题 08.10. 颜色填充
class Solution {
public int[][] floodFill(int[][] image, int sr, int sc, int newColor) {
helper(image, sr, sc, image[sr][sc], newColor);
return image;
}
private void helper(int[][] image, int i, int j, int oldColor, int newColor){
if(i < 0 || i >= image.length || j < 0 || j >= image[0].length || image[i][j] != oldColor || image[i][j] == newColor) return;
image[i][j] = newColor;
helper(image, i+1, j, oldColor, newColor);
helper(image, i-1, j, oldColor, newColor);
helper(image, i, j+1, oldColor, newColor);
helper(image, i, j-1, oldColor, newColor);
}
}
面试题 08.11. 硬币
class Solution {
static final int MOD = 1000000007;
public int waysToChange(int n) {
int ans = 0;
for (int i = 0; i * 25 <= n; ++i) {
int rest = n - i * 25;
int a = rest / 10;
int b = rest % 10 / 5;
ans = (ans + (int) ((long) (a + 1) * (a + b + 1) % MOD)) % MOD;
}
return ans;
}
}
面试题 08.12. 八皇后
class Solution {
public List<List<String>> solveNQueens(int n) {
int[] queens = new int[n];
Arrays.fill(queens, -1);
List<List<String>> solutions = new ArrayList<List<String>>();
solve(solutions, queens, n, 0, 0, 0, 0);
return solutions;
}
public void solve(List<List<String>> solutions, int[] queens, int n, int row, int columns, int diagonals1, int diagonals2) {
if (row == n) {
List<String> board = generateBoard(queens, n);
solutions.add(board);
} else {
int availablePositions = ((1 << n) - 1) & (~(columns | diagonals1 | diagonals2));
while (availablePositions != 0) {
int position = availablePositions & (-availablePositions);
availablePositions = availablePositions & (availablePositions - 1);
int column = Integer.bitCount(position - 1);
queens[row] = column;
solve(solutions, queens, n, row + 1, columns | position, (diagonals1 | position) << 1, (diagonals2 | position) >> 1);
queens[row] = -1;
}
}
}
public List<String> generateBoard(int[] queens, int n) {
List<String> board = new ArrayList<String>();
for (int i = 0; i < n; i++) {
char[] row = new char[n];
Arrays.fill(row, '.');
row[queens[i]] = 'Q';
board.add(new String(row));
}
return board;
}
}
面试题 08.13. 堆箱子
class Solution {
public int pileBox(int[][] box) {
Arrays.sort(box, (i, j) -> (i[0] != j[0] ? i[0] - j[0] : (i[1] != j[1] ? i[1] - j[1] : i[2] - j[2])));
int[] dp = new int[box.length];
for (int i = 0; i < dp.length; i++) {
dp[i] = box[i][2];
for (int j = 0; j < i; j++)
if (box[i][0] > box[j][0] && box[i][1] > box[j][1] && box[i][2] > box[j][2])
dp[i] = Math.max(dp[i], box[i][2] + dp[j]);
}
return Arrays.stream(dp).max().orElse(0);
}
}
面试题 10.01. 合并排序的数组
class Solution {
public void merge(int[] A, int m, int[] B, int n) {
int k = n-- + m-- - 1;
while (n >= 0 && m >= 0) {
if (A[m] > B[n]) A[k--] = A[m--];
else A[k--] = B[n--];
}
while (n >= 0) {
A[k--] = B[n--];
}
}
}
面试题 10.02. 变位词组
class Solution {
static int[] nums = new int[]{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101};
public List<List<String>> groupAnagrams(String[] ss) {
List<List<String>> ans = new ArrayList<>();
Map<Long, List<String>> map = new HashMap<>();
for (String s : ss) {
long cur = 1;
for (char c : s.toCharArray()) cur *= nums[c - 'a'];
List<String> list = map.getOrDefault(cur, new ArrayList<>());
list.add(s);
map.put(cur, list);
}
for (long key : map.keySet()) ans.add(map.get(key));
return ans;
}
}
面试题 10.03. 搜索旋转数组
class Solution {
public int search(int[] arr, int target) {
int n = arr.length;
int result = -1;
int l = 0, r = n - 1;
while (l <= r) {
int mid = (l + r + 1) >> 1;
if (arr[l] == target) return l;
else if (arr[l] == arr[mid]) l++;
else if (arr[l] < arr[mid]) {
if (arr[l] > target || arr[mid] < target) l = mid;
else {
l = l + 1;
r = mid;
}
} else {
if (arr[l] > target && arr[mid] < target) l = mid;
else {
l = l + 1;
r = mid;
}
}
}
return result;
}
}
面试题 10.05. 稀疏数组搜索
class Solution {
public int findString(String[] words, String s) {
int left = 0, right = words.length - 1, m;
while (left <= right) {
m = (left + right) >> 1;
while (m < right && "".equals(words[m])) m++;
if (words[m].compareTo(s) > 0 || "".equals(words[m])) right = m - 1;
else if (words[m].compareTo(s) < 0) left = m + 1;
else return m;
}
return -1;
}
}
面试题 10.09. 排序矩阵查找
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int M = matrix.length;
if (M == 0) return false;
int N = matrix[0].length;
if (N == 0) return false;
int i = M - 1, j = 0;
while (i >= 0 && j < N) {
if (matrix[i][j] == target) return true;
else if (matrix[i][j] > target) i--;
else j++;
}
return false;
}
}
面试题 10.11. 峰与谷
class Solution {
public void wiggleSort(int[] nums) {
Arrays.sort(nums);
for (int i = 0; i < nums.length - 1; i += 2) {
int temp = nums[i];
nums[i] = nums[i + 1];
nums[i + 1] = temp;
}
}
}
面试题 16.01. 交换数字
class Solution {
public int[] swapNumbers(int[] numbers) {
numbers[0] = numbers[0] ^ numbers[1];
numbers[1] = numbers[0] ^ numbers[1];
numbers[0] = numbers[1] ^ numbers[0];
return numbers;
}
}
面试题 16.02. 单词频率
class WordsFrequency {
private Map<String, Integer> map = new HashMap<>();
public WordsFrequency(String[] book) {
for (String name : book) {
map.put(name, map.getOrDefault(name, 0) + 1);
}
}
public int get(String word) {
return map.getOrDefault(word, 0);
}
}
面试题 16.04. 井字游戏
class Solution {
public String tictactoe(String[] board) {
int m = board.length;
boolean hasBlank = false;
int rowX, rowO, colX, colO;
for (int i = 0; i < m; i++) {
rowX = 0;rowO = 0;colX = 0;colO = 0;
for (int j = 0; j < m; j++) {
if (board[i].charAt(j) == ' ') hasBlank = true;
if (board[i].charAt(j) == 'X') rowX++;
else if (board[i].charAt(j) == 'O') rowO++;
if (board[j].charAt(i) == 'X') colX++;
else if (board[j].charAt(i) == 'O') colO++;
}
if (rowX == m || colX == m) return "X";
if (rowO == m || colO == m) return "O";
}
int leftTopX = 0, leftTopO = 0, leftBottomX = 0, leftBottomO = 0;
for (int i = 0; i < m; i++) {
if (board[i].charAt(i) == 'X') leftTopX++;
else if (board[i].charAt(i) == 'O') leftTopO++;
if (board[m - 1 - i].charAt(i) == 'X') leftBottomX++;
else if (board[m - 1 - i].charAt(i) == 'O') leftBottomO++;
}
if (leftTopX == m || leftBottomX == m) return "X";
if (leftTopO == m || leftBottomO == m) return "O";
return hasBlank ? "Pending" : "Draw";
}
}
面试题 16.05. 阶乘尾数
class Solution {
public int trailingZeroes(int n) {
int res = 0;
while (n > 0) {
n /= 5;
res += n;
}
return res;
}
}
面试题 16.06. 最小差
class Solution {
public int smallestDifference(int[] a, int[] b) {
int alen = a.length, blen = b.length;
Arrays.sort(a);
Arrays.sort(b);
int minVal = Integer.MAX_VALUE, i = 0, j = 0;
while (i < alen && j < blen) {
long diff = a[i] - b[j];
minVal = (int) Math.min(Math.abs(diff), minVal);
if (diff < 0) i++;
else j++;
}
return minVal;
}
}
面试题 16.07. 最大数值
class Solution {
public int maximum(int a, int b) {
int k = (int) (((long) a - (long) b) >>> 63 & 1);
return a * (1 - k) + b * k;
}
}
面试题 16.08. 整数的英语表示
class Solution {
String[] singles = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"};
String[] teens = {"Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
String[] tens = {"", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
String[] thousands = {"", "Thousand", "Million", "Billion"};
public String numberToWords(int num) {
if (num == 0) {
return "Zero";
}
StringBuffer sb = new StringBuffer();
for (int i = 3, unit = 1000000000; i >= 0; i--, unit /= 1000) {
int curNum = num / unit;
if (curNum != 0) {
num -= curNum * unit;
sb.append(toEnglish(curNum)).append(thousands[i]).append(" ");
}
}
return sb.toString().trim();
}
public String toEnglish(int num) {
StringBuffer curr = new StringBuffer();
int hundred = num / 100;
num %= 100;
if (hundred != 0) {
curr.append(singles[hundred]).append(" Hundred ");
}
int ten = num / 10;
if (ten >= 2) {
curr.append(tens[ten]).append(" ");
num %= 10;
}
if (num > 0 && num < 10) {
curr.append(singles[num]).append(" ");
} else if (num >= 10) {
curr.append(teens[num - 10]).append(" ");
}
return curr.toString();
}
}
面试题 16.10. 生存人数
class Solution {
public int maxAliveYear(int[] birth, int[] death) {
int[] change = new int[102];
for (int i = 0; i < birth.length; i++) {
change[birth[i] - 1900]++;
change[death[i] - 1899]--;
}
int maxAlive = 0;
int curAlive = 0;
int theYear = 1900;
for (int i = 0; i < 101; i++) {
curAlive += change[i];
if (curAlive > maxAlive) {
maxAlive = curAlive;
theYear = 1900 + i;
}
}
return theYear;
}
}
面试题 16.11. 跳水板
class Solution {
public int[] divingBoard(int shorter, int longer, int k) {
if (k == 0) return new int[0];
if (shorter == longer) return new int[]{shorter * k};
int[] lengths = new int[k + 1];
for (int i = 0; i <= k; i++) lengths[i] = shorter * (k - i) + longer * i;
return lengths;
}
}
面试题 16.14. 最佳直线
class Solution {
public int[] bestLine(int[][] points) {
int n = points.length;
Map<Double, Integer>[] dp = new Map[n];
int maxCnt = 0, l = 0, r = 0;
for (int i = n - 1; i >= 0; --i) {
dp[i] = new HashMap<>();
for (int j = n - 1; j > i; --j) {
int dx = points[i][0] - points[j][0], dy = points[i][1] - points[j][1];
double k = dx == 0 ? Double.POSITIVE_INFINITY : dy == 0 ? 0 : (double) dy / dx;
int cnt = dp[j].getOrDefault(k, 1) + 1;
dp[i].put(k, cnt);
if (cnt >= maxCnt) {
maxCnt = cnt;
l = i;
r = j;
}
}
}
return new int[]{l, r};
}
}
面试题 16.15. 珠玑妙算
class Solution {
public int[] masterMind(String solution, String guess) {
int[][] hash = new int[26][2];
int[] ans = new int[2];
var s = solution.toCharArray();
var g = guess.toCharArray();
for (int i = 0; i < 4; i++) {
if (s[i] == g[i]) {
ans[0]++;
} else {
hash[s[i] - 'A'][0]++;
hash[g[i] - 'A'][1]++;
}
}
for (int[] arr : hash) { ans[1] += arr[0] > arr[1] ? arr[1] : arr[0];
return ans;
}
}
面试题 16.16. 部分排序
class Solution {
public int[] subSort(int[] array) {
if (array == null || array.length < 1) return new int[]{-1, -1};
int max = array[0], right = -1, n = array.length;
for (int i = 1; i < n; i++) {
if (array[i] >= max) max = array[i];
else right = i;
}
if (right == -1) return new int[]{-1, -1};
int min = array[n - 1], left = -1;
for (int i = n - 1; i >= 0; i--) {
if (array[i] <= min) min = array[i];
else left = i;
}
return new int[]{left, right};
}
}
面试题 16.17. 连续数列
class Solution {
public int maxSubArray(int[] nums) {
int dp = 0, max = Integer.MIN_VALUE;
for(int i = 0; i < nums.length; i++){
dp = Math.max(nums[i], dp + nums[i]);
max = Math.max(dp, max);
}
return max;
}
}
面试题 16.19. 水域大小
class Solution {
int[][] grid_use;
int[] dx = {-1, 1, 0, 0, -1, -1, 1, 1};
int[] dy = {0, 0, -1, 1, -1, 1, -1, 1};
public int[] pondSizes(int[][] land) {
grid_use = land;
List<Integer> list = new ArrayList<>();
for (int i = 0; i < land.length; i++){
for (int j = 0; j < land[0].length; j++){
if (land[i][j] == 0)
list.add(dfs(land, i, j));
}
}
int[] res = new int[list.size()];
for (int i = 0; i < list.size(); i++)
res[i] = list.get(i);
Arrays.sort(res);
return res;
}
public int dfs(int[][] land, int x, int y){
int area = 1;
grid_use[x][y] = 1;
for (int i = 0; i < 8; i++){
int a = x + dx[i];
int b = y + dy[i];
if (a >= 0 && a < land.length && b >= 0 && b < land[0].length && grid_use[a][b] == 0){
area = area + dfs(land, a, b);
}
}
return area;
}
}
面试题 16.20. T9键盘
class Solution {
public List<String> getValidT9Words(String num, String[] words) {
List<String> res = new ArrayList<>();
int length = num.length();
int[] key = {2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6,
7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9};
boolean flag;
for (String word: words) {
flag = true;
for (int i = 0; i < length; i++) {
if (num.charAt(i) != key[word.charAt(i) - 'a'] + '0') {
flag = false;
break;
}
}
if (flag) res.add(word);
}
return res;
}
}
面试题 16.21. 交换和
class Solution {
public int[] findSwapValues(int[] array1, int[] array2) {
int sum1 = 0, sum2 = 0;
Set<Integer> container = new HashSet<>();
for (int num : array1) sum1 += num;
for (int num : array2) {
container.add(num);
sum2 += num;
}
int diff = sum1 - sum2;
if (diff % 2 != 0) return new int[]{};
diff /= 2;
for (int num : array1) if (container.contains(num - diff)) return new int[]{num, num - diff};
return new int[]{};
}
}
面试题 16.22. 兰顿蚂蚁
class Solution {
private class Position {
int x, y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof Position)) return false;
Position o = (Position) obj;
return x == o.x && y == o.y;
}
@Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
}
public List<String> printKMoves(int K) {
char[] direction = {'L', 'U', 'R', 'D'};
int[][] offset = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
Position antPos = new Position(0, 0);
int antDir = 2;
Set<Position> blackSet = new HashSet<>();
while (K > 0) {
Position t = new Position(antPos.x, antPos.y);
if (blackSet.add(t)) antDir = (antDir + 1) % 4;
else {
antDir = (antDir + 3) % 4;
blackSet.remove(t);
}
antPos.x += offset[antDir][0];
antPos.y += offset[antDir][1];
K--;
}
int left = antPos.x, top = antPos.y, right = antPos.x, bottom = antPos.y;
for (Position pos : blackSet) {
left = Math.min(pos.x, left);
top = Math.min(pos.y, top);
right = Math.max(pos.x, right);
bottom = Math.max(pos.y, bottom);
}
char[][] grid = new char[bottom - top + 1][right - left + 1];
for (char[] row : grid)
Arrays.fill(row, '_');
for (Position pos : blackSet)
grid[pos.y - top][pos.x - left] = 'X';
grid[antPos.y - top][antPos.x - left] = direction[antDir];
List<String> result = new ArrayList<>();
for (char[] row : grid)
result.add(String.valueOf(row));
return result;
}
}
面试题 16.24. 数对和
class Solution {
public List<List<Integer>> pairSums(int[] nums, int target) {
Arrays.sort(nums);
int start = 0, end = nums.length - 1;
List<List<Integer>> ans = new ArrayList<>();
while (start < end) {
if (nums[start] + nums[end] == target) {
List<Integer> list = new ArrayList<>();
list.add(nums[start]);
list.add(nums[end]);
ans.add(list);
start++;
end--;
} else if (nums[start] + nums[end] < target) start++;
else end--;
}
return ans;
}
}
面试题 16.25. LRU 缓存
public class LRUCache {
class DLinkedNode {
int key;
int value;
DLinkedNode prev;
DLinkedNode next;
public DLinkedNode() {
}
public DLinkedNode(int _key, int _value) {
key = _key;
value = _value;
}
}
private Map<Integer, DLinkedNode> cache = new HashMap<>();
private int size;
private int capacity;
private DLinkedNode head, tail;
public LRUCache(int capacity) {
this.size = 0;
this.capacity = capacity;
head = new DLinkedNode();
tail = new DLinkedNode();
head.next = tail;
tail.prev = head;
}
public int get(int key) {
DLinkedNode node = cache.get(key);
if (node == null) return -1;
moveToHead(node);
return node.value;
}
public void put(int key, int value) {
DLinkedNode node = cache.get(key);
if (node == null) {
DLinkedNode newNode = new DLinkedNode(key, value);
cache.put(key, newNode);
addToHead(newNode);
++size;
if (size > capacity) {
DLinkedNode tail = removeTail();
cache.remove(tail.key);
--size;
}
} else {
node.value = value;
moveToHead(node);
}
}
private void addToHead(DLinkedNode node) {
node.prev = head;
node.next = head.next;
head.next.prev = node;
head.next = node;
}
private void removeNode(DLinkedNode node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
private void moveToHead(DLinkedNode node) {
removeNode(node);
addToHead(node);
}
private DLinkedNode removeTail() {
DLinkedNode res = tail.prev;
removeNode(res);
return res;
}
}
面试题 16.26. 计算器
class Solution {
public int calculate(String s) {
Deque<Integer> stack = new LinkedList<>();
char opt = '+';
int num = 0;
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (Character.isDigit(ch))num = num * 10 + (ch - '0');
if ((!Character.isDigit(ch) && ch != ' ') || i == s.length() - 1) {
if (opt == '+')stack.push(num);
else if (opt == '-') stack.push(-num);
else if (opt == '*')stack.push(stack.pop() * num);
else stack.push(stack.pop() / num);
num = 0;
opt = ch;
}
}
int res = 0;
while (!stack.isEmpty())res += stack.pop();
return res;
}
}
面试题 17.04. 消失的数字
class Solution {
public int missingNumber(int[] nums) {
int res = 0;
for (int i = 0; i < nums.length; i++) {
res ^= i;
res ^= nums[i];
}
return res ^ nums.length;
}
}
面试题 17.05. 字母与数字
class Solution {
public String[] findLongestSubarray(String[] array) {
int len = array.length;
int[] memo = new int[(len << 1) + 1];
Arrays.fill(memo, -2);
memo[len] = -1;
int res = 0, count = 0, begin = 0, end = 0;
for (int i = 0; i < len; ++i) {
boolean is_num = true;
for (char c : array[i].toCharArray())
if (c < '0' || c > '9') {
is_num = false;
break;
}
count += is_num ? -1 : 1;
if (memo[count + len] <= -2)
memo[count + len] = i;
else if (i - memo[count + len] > res) {
begin = memo[count + len] + 1;
end = i + 1;
res = i - memo[count + len];
}
}
return Arrays.copyOfRange(array, begin, end);
}
}
面试题 17.06. 2出现的次数
class Solution {
public int numberOf2sInRange(int n) {
if (n == 0) return 0;
int digit = (int) Math.log10(n) + 1;
int[][] dp = new int[digit + 1][2];
dp[1][0] = n % 10 >= 2 ? 1 : 0;
dp[1][1] = 1;
for (int i = 2; i <= digit; i++) {
int k = n / ((int) Math.pow(10, i - 1)) % 10;
dp[i][0] = k * dp[i - 1][1] + dp[i - 1][0];
if (k == 2) dp[i][0] += n % (int) Math.pow(10, i - 1) + 1;
else if (k > 2) dp[i][0] += (int) Math.pow(10, i - 1)
dp[i][1] = 10 * dp[i - 1][1] + (int) Math.pow(10, i - 1);
}
return dp[digit][0];
}
}
面试题 17.08. 马戏团人塔
class Solution {
public int bestSeqAtIndex(int[] height, int[] weight) {
int len = height.length, res = 0;
int[][] person = new int[len][2];
for (int i = 0; i < len; ++i) person[i] = new int[]{height[i], weight[i]};
Arrays.sort(person, (a, b) -> a[0] == b[0] ? b[1] - a[1] : a[0] - b[0]);
int[] dp = new int[len];
for (int[] pair : person) {
int i = Arrays.binarySearch(dp, 0, res, pair[1]);
if (i < 0) i = -(i + 1);
dp[i] = pair[1];
if (i == res) ++res;
}
return res;
}
}
面试题 17.09. 第 k 个数
class Solution {
public int getKthMagicNumber(int k) {
int i3 = 0, i5 = 0, i7 = 0;
int dp[] = new int[k];
dp[0] = 1;
for (int i = 1; i < k; i++) {
dp[i] = Math.min(Math.min(3 * dp[i3], 5 * dp[i5]), 7 * dp[i7]);
if (dp[i] == 3 * dp[i3]) i3++;
if (dp[i] == 5 * dp[i5]) i5++;
if (dp[i] == 7 * dp[i7]) i7++;
}
return dp[k - 1];
}
}
面试题 17.10. 主要元素
class Solution {
public int majorityElement(int[] nums) {
int n = nums.length;
int x = -1, cnt = 0;
for (int i : nums) {
if (cnt == 0) {
x = i;
cnt = 1;
} else cnt += x == i ? 1 : -1;
}
cnt = 0;
for (int i : nums) if (x == i) cnt++;
return cnt > n / 2 ? x : -1;
}
}
面试题 17.11. 单词距离
class Solution {
public int findClosest(String[] words, String word1, String word2) {
int start = Integer.MIN_VALUE / 2;
int end = Integer.MAX_VALUE / 2;
int ans = Integer.MAX_VALUE;
for(int i=0; i<words.length; ++i){
if(words[i].equals(word1)){
start = i;
ans = Math.min(ans, Math.abs(end-start));
}
if(words[i].equals(word2)){
end = i;
ans = Math.min(ans, Math.abs(end-start));
}
}
return ans;
}
}
面试题 17.12. BiNode
class Solution {
TreeNode head = null, pre = null;
public TreeNode convertBiNode(TreeNode root) {
if (root == null) return null;
convertBiNode(root.left);
if (head == null) head = root;
else pre.right = root;
pre = root;
root.left = null;
convertBiNode(root.right);
return head;
}
}
面试题 17.13. 恢复空格
class Solution {
public int respace(String[] dictionary, String sentence) {
int m = sentence.length();
int[] dp = new int[m + 1];
for (int i = 1; i <= m; i++) {
for (String word : dictionary) {
int len = word.length();
if (i >= len && word.equals(sentence.substring(i - len, i))) dp[i] = Math.max(dp[i], dp[i - len] + len);
else dp[i] = Math.max(dp[i], dp[i - 1]);
}
}
return m - dp[m];
}
}
面试题 17.14. 最小K个数
class Solution {
int k;
public int[] smallestK(int[] arr, int _k) {
k = _k;
int n = arr.length;
int[] ans = new int[k];
if (k == 0) return ans;
qsort(arr, 0, n - 1);
for (int i = 0; i < k; i++) ans[i] = arr[i];
return ans;
}
void qsort(int[] arr, int l, int r) {
if (l >= r) return ;
int i = l, j = r;
int ridx = new Random().nextInt(r - l + 1) + l;
swap(arr, ridx, l);
int x = arr[l];
while (i < j) {
while (i < j && arr[j] >= x) j--;
while (i < j && arr[i] <= x) i++;
swap(arr, i, j);
}
swap(arr, i, l);
if (i > k) qsort(arr, l, i - 1);
if (i < k) qsort(arr, i + 1, r);
}
void swap(int[] arr, int l, int r) {
int tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
}
}
面试题 17.15. 最长单词
class Solution {
public String longestWord(String[] words) {
Arrays.sort(words, Comparator
.comparingInt(String::length).reversed()
.thenComparing(Function.identity()));
Set<String> set = new HashSet<>(Arrays.asList(words));
for (String word : words) {
set.remove(word);
if (valid(set, word)) return word;
set.add(word);
}
return "";
}
boolean valid(Set<String> set, String word) {
for (int i = 1, n = word.length(); i < n; ++i) {
String left = word.substring(0, i);
if (!set.contains(left)) continue;
String right = word.substring(i);
if (set.contains(right)) return true;
if (valid(set, right)) return true;
}
return false;
}
}
面试题 17.16. 按摩师
class Solution {
public int massage(int[] nums) {
int a = 0, b = 0;
for (int i = 0; i < nums.length; i++) {
int c = Math.max(b, a + nums[i]);
a = b;
b = c;
}
return b;
}
}
面试题 17.18. 最短超串
class Solution {
public int[] shortestSeq(int[] big, int[] small) {
int[] res = {};
int smallLen = small.length, bigLen = big.length, left = 0, right = 0, minLen = bigLen;
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < smallLen; i++) map.putIfAbsent(small[i], 1);
while (right < bigLen) {
if (map.containsKey(big[right])) {
if (map.get(big[right]) > 0) smallLen--;
map.put(big[right], map.get(big[right]) - 1);
}
while (smallLen == 0) {
if (right - left < minLen) {
minLen = right - left;
res = new int[]{left, right};
}
if (map.containsKey(big[left])) {
map.put(big[left], map.get(big[left]) + 1);
if (map.get(big[left]) > 0) {
smallLen++;
}
}
left++;
}
right++;
}
return res;
}
}
面试题 17.19. 消失的两个数字
class Solution {
public int[] missingTwo(int[] nums) {
int len = nums.length;
int[] temp = new int[len + 2];
int[] res = new int[2];
for (int num : nums) temp[num - 1]--;
int index = 0;
for (int i = 0; i < temp.length; i++) {
if (temp[i] == 0) res[index++] = i + 1;
}
return res;
}
}
面试题 17.20. 连续中值
class MedianFinder {
PriorityQueue<Integer> left, right;
boolean isLeft;
public MedianFinder() {
left = new PriorityQueue<>((x, y) -> y - x);
right = new PriorityQueue<>();
}
public void addNum(int num) {
left.offer(num);
right.offer(left.poll());
if (left.size() < right.size())
left.offer(right.poll());
}
public double findMedian() {
if (left.size() > right.size())
return left.peek();
return (left.peek() + right.peek()) / 2.0;
}
}
面试题 17.21. 直方图的水量
class Solution {
public int trap(int[] height) {
if (height==null||height.length<=2)return 0;
int leftMax=height[0],rightMax=height[height.length-1];
int left=0,right=height.length-2;
int res=0;
while (left<=right){
if (leftMax<rightMax){
if (height[left]<leftMax){
res+=leftMax-height[left];
}else {
leftMax=height[left];
}
++left;
}else {
if (height[right]<rightMax){
res+=rightMax-height[right];
}else {
rightMax=height[right];
}
--right;
}
}
return res;
}
}
面试题 17.22. 单词转换
class Solution {
public List<String> findLadders(String beginWord, String endWord, List<String> wordList) {
Queue<String> queue = new LinkedList<String>();
List<String> ans = new LinkedList<String>();
boolean[] visited = new boolean[wordList.size()];
HashMap<String, String> map = new HashMap<>();
if (!wordList.contains(endWord)) return ans;
queue.add(beginWord);
boolean flag = false;
while (queue.size() != 0) {
String queueHead = queue.poll();
if (queueHead.equals(endWord)) {
flag = true;
break;
}
for (int i = 0; i < wordList.size(); i++) {
if (!visited[i] && compare(wordList.get(i), queueHead)) {
queue.add(wordList.get(i));
visited[i] = true;
map.put(wordList.get(i), queueHead);
}
}
}
if (!flag) return ans;
String key = endWord;
while (!map.get(key).equals(beginWord)) {
ans.add(key);
key = map.get(key);
}
ans.add(key);
ans.add(map.get(key));
Collections.reverse(ans);
return ans;
}
public static boolean compare(String word1, String word2) {
int diff = 0;
for (int i = 0; i < word1.length(); i++) {
if (word1.charAt(i) != word2.charAt(i)) {
diff++;
if (diff >= 2) {
return false;
}
}
}
return true;
}
}
面试题 17.23. 最大黑方阵
class Solution {
private int global_row, global_col;
private int[][] global_matrix;
private int[] res = new int[3];
public int[] findSquare(int[][] matrix) {
global_matrix = matrix;
if ((global_row = matrix.length) < 1) return new int[0];
global_col = matrix[0].length;
for (int i = 0; i < global_row - res[2]; ++i)
and_operate(i);
return res[2] > 0 ? res : new int[0];
}
private void and_operate(int cur_idx) {
int[] first_row = global_matrix[cur_idx], base = first_row.clone();
if (res[2] < 1)
for (int i = 0; i < global_col; ++i)
if (first_row[i] < 1) {
res[2] = 1;
res[0] = cur_idx;
res[1] = i;
break;
}
int offset = 0;
for (int i = cur_idx + 1; i < global_row; ++i) {
++offset;
int[] last_row = global_matrix[i];
for (int j = 0; j < global_col; ++j)
base[j] |= global_matrix[i][j];
List<Integer> idx_list = new ArrayList<>();
int count = 0, temp_idx = 0;
for (; temp_idx < global_col - offset; ++temp_idx) {
if (base[temp_idx] == 0) {
++count;
if (base[temp_idx + offset] == 0)
idx_list.add(temp_idx);
}
}
if (count < 2) {
for (; temp_idx < global_col; ++temp_idx)
if (base[temp_idx] == 0 && ++count == 2)
break;
if (count < 2)
return;
}
Loop:
for (int begin_idx : idx_list) {
int end_idx = begin_idx + offset;
for (int l = begin_idx + 1; l < end_idx; ++l)
if (first_row[l] > 0 || last_row[l] > 0)
continue Loop;
if (res[2] < offset + 1) {
res[2] = offset + 1;
res[0] = cur_idx;
res[1] = begin_idx;
}
}
}
}
}
面试题 17.24. 最大子矩阵
class Solution {
public int[] getMaxMatrix(int[][] matrix) {
int[] ans = new int[4];
int N = matrix.length, M = matrix[0].length;
int[] b = new int[M];
int sum = 0, maxsum = Integer.MIN_VALUE, bestr1 = 0, bestc1 = 0;
for (int i = 0; i < N; i++) {
for (int t = 0; t < M; t++) b[t] = 0;
for (int j = i; j < N; j++) {
sum = 0;
for (int k = 0; k < M; k++) {
b[k] += matrix[j][k];
if (sum > 0) {
sum += b[k];
} else {
sum = b[k];
bestr1 = i;
bestc1 = k;
}
if (sum > maxsum) {
maxsum = sum;
ans[0] = bestr1;
ans[1] = bestc1;
ans[2] = j;
ans[3] = k;
}
}
}
}
return ans;
}
}
面试题 17.26. 稀疏相似度
class Solution {
public List<String> computeSimilarities(int[][] docs) {
HashMap<Integer, List<Integer>> map = new HashMap<>();
int[][] help = new int[docs.length][docs.length];
for (int i = 0; i < docs.length; i++) {
for (int j : docs[i]) {
List<Integer> list = map.get(j);
if (list == null) {
list = new ArrayList<Integer>();
map.put(j, list);
} else for (int k : list) help[i][k]++;
list.add(i);
}
}
List<String> retList = new ArrayList<>();
for (int i = 0; i < docs.length; i++)
for (int j = i; j < docs.length; j++)
if (help[j][i] != 0)
retList.add(String.format("%d,%d: %.4f", i, j, 1.0 * help[j][i] / (docs[i].length + docs[j].length - help[j][i])));
return retList;
}
}
面试题19. 正则表达式匹配
class Solution {
public boolean isMatch(String s, String p) {
int m = s.length();
int n = p.length();
boolean[][] f = new boolean[m + 1][n + 1];
f[0][0] = true;
for (int i = 0; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (p.charAt(j - 1) == '*') {
f[i][j] = f[i][j - 2];
if (matches(s, p, i, j - 1)) {
f[i][j] = f[i][j] || f[i - 1][j];
}
} else {
if (matches(s, p, i, j)) {
f[i][j] = f[i - 1][j - 1];
}
}
}
}
return f[m][n];
}
public boolean matches(String s, String p, int i, int j) {
if (i == 0) {
return false;
}
if (p.charAt(j - 1) == '.') {
return true;
}
return s.charAt(i - 1) == p.charAt(j - 1);
}
}
面试题32 - I. 从上到下打印二叉树
class Solution {
public int[] levelOrder(TreeNode root) {
if (root == null) return new int[0];
Queue<TreeNode> queue = new LinkedList<>();
List<Integer> list = new ArrayList<>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
list.add(node.val);
if (node.left != null) queue.add(node.left);
if (node.right != null) queue.add(node.right);
}
return list.stream().mapToInt(Integer::intValue).toArray();
}
}