剑指offer-20200224
题目 :找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例 1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
思路 :利用集合元素的唯一性,找出相同的元素。
它考察的是程序员的沟通能力,先问面试官要时间/空间需求!!!
只是时间优先就用字典,
还有空间要求,就用指针+原地排序数组,
如果面试官要求空间O(1)并且不能修改原数组,还得写成二分法!!!
code
public int findRepeatNumber(int[] nums) {
Set<Integer> set = new HashSet<>();
for(int i=0;i<nums.length;i++){
if(!set.add(nums[i])){
return nums[i];
}
}
return -1;
}
题目 :二维数组中的查找
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
示例:
现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。
给定 target = 20,返回 false
思路 :以左下角的值为基点,判断与target的大小,当较小的时候,行数减一。反着,列数加一。
code
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
int row = matrix.length-1;
int col = 0;
while(row >= 0 && col <=matrix[0].length-1){
if(matrix[row][col] == target){
return true;
}
if(matrix[row][col] > target){
row--;
}else{
col++;
}
}
return false;
}
}
题目 :替换空格
请实现一个函数,把字符s中的每个空格替换成"%20"。
思路 :找到空格,重新分配空间。
code
class Solution {
public String replaceSpace(String s) {
int count=0;
int j=0;
char[] c1 = s.toCharArray();
for(int i=0;i<c1.length;i++){
if(c1[i] == ' '){
count++;
}
}
int lengthNew = 2 * count + c1.length;
char[] newArr = new char[lengthNew];
for(int i=0;i<c1.length;i++){
if(c1[i] == ' '){
newArr[j++] = '%';
newArr[j++] = '2';
newArr[j++] = '0';
}else{
newArr[j++]=c1[i];
}
}
return new String(newArr);
}
}
题目 :输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
示例 1:
输入:head = [1,3,2]
输出:[2,3,1]
思路 :利用栈,反向存储。
code
class Solution {
public int[] reversePrint(ListNode head) {
Stack<Integer> stack = new Stack<>();
while(head != null){
stack.push(head.val);
head = head.next;
}
int[] res = new int[stack.size()];
int cnt = 0;
while(!stack.isEmpty()){
res[cnt++] = stack.pop();
}
return res;
}
}
题目 :重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建改二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
思路 :通过前序遍历找到根节点。中序遍历通过根节点可以确定左子树和右子树。
code
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder == null || preorder.length == 0) {
return null;
}
Map<Integer, Integer> indexMap = new HashMap<Integer, Integer>();
int length = preorder.length;
for (int i = 0; i < length; i++) {
indexMap.put(inorder[i], i);
}
TreeNode root = buildTree(preorder, 0, length - 1, inorder, 0, length - 1, indexMap);
return root;
}
public TreeNode buildTree(int[] preorder, int preorderStart, int preorderEnd, int[] inorder, int inorderStart, int inorderEnd, Map<Integer, Integer> indexMap) {
if (preorderStart > preorderEnd) {
return null;
}
int rootVal = preorder[preorderStart];
TreeNode root = new TreeNode(rootVal);
if (preorderStart == preorderEnd) {
return root;
} else {
int rootIndex = indexMap.get(rootVal);
int leftNodes = rootIndex - inorderStart, rightNodes = inorderEnd - rootIndex;
TreeNode leftSubtree = buildTree(preorder, preorderStart + 1, preorderStart + leftNodes, inorder, inorderStart, rootIndex - 1, indexMap);
TreeNode rightSubtree = buildTree(preorder, preorderEnd - rightNodes + 1, preorderEnd, inorder, rootIndex + 1, inorderEnd, indexMap);
root.left = leftSubtree;
root.right = rightSubtree;
return root;
}
}
}