剑指 Offer 4. 二维数组中的查找、9. 用两个栈实现队列、26. 树的子结构、35. 复杂链表的复制、53 - I. 在排序数组中查找数字 I
题目描述:
[4]
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
[9]
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
[26]
[35]
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
[53]
统计一个数字在排序数组中出现的次数。
考察重点:
[4]
同leetcode240题。从0行matrix[0].length-1开始查询,小于target则行++,大于target则列–。
[9]
A栈负责输出,B栈负责输入。平时所有元素存在B,输出时先将B元素取出并放入A,输出A栈顶元素,再将A元素取出并放回B。
[26]
先通过递归遍历A,查询与B的根节点相等的所有节点,依次作为A的子树根节点,再使用递归遍历判断这些子树与B是否完全相等。
[35]
本题需要深拷贝,所以一次遍历先使用Map记录新旧节点的对应关系,再一次遍历填补random指针。
[53]
两次二分查找,分别锁定重复数字的左右边界点。
[4]代码
public boolean findNumberIn2DArray(int[][] matrix, int target) {if (matrix.length == 0) return false;int n = matrix.length, m = matrix[0].length;int row = 0, column = m - 1;while (row < n && column >= 0) {int num = matrix[row][column];if (num == target) {return true;} else if (num > target) {column--;} else {row++;}}return false;}
[9]代码
class CQueue {private LinkedList<Integer> A;private LinkedList<Integer> B;public CQueue() {A = new LinkedList<Integer>();B = new LinkedList<Integer>();}public void appendTail(int value) {B.addLast(value);}public int deleteHead() {if(B.isEmpty()){return -1;}while(!B.isEmpty()){A.addLast(B.removeLast());}int res = A.removeLast();while(!A.isEmpty()){B.addLast(A.removeLast());}return res;}
}/*** Your CQueue object will be instantiated and called as such:* CQueue obj = new CQueue();* obj.appendTail(value);* int param_2 = obj.deleteHead();*/
[26]代码
func recursion(A *TreeNode, B *TreeNode)bool {if (A == nil && B == nil) || (A != nil && B == nil){return true}if A == nil && B != nil{return false}left := recursion(A.Left, B.Left) right := recursion(A.Right, B.Right)if A.Val == B.Val && left && right{return true}return false
}func recursionA(A *TreeNode, B *TreeNode, mark *bool) {if A == nil || *mark == true{return }recursionA(A.Left, B, mark) temp := Bif A.Val == B.Val && *mark != true{ //这里需要加mark是否为true的判断,防止再次进入判断导致mark被置为false*mark = recursion(A, B)}B = temprecursionA(A.Right, B, mark)
}
func isSubStructure(A *TreeNode, B *TreeNode) bool {if B == nil{return false}mark := falserecursionA(A, B, &mark)return mark
}
[35]代码
public Node copyRandomList(Node head) {Map<Node, Node> map = new HashMap<>(); //map记录旧链表与新链表节点的对应关系Node newHead = new Node(0);Node recHead = head;Node temp = newHead;while(head != null){ //先将所有元素除random外的属性,都填入Node newNode = new Node(head.val);temp.next = newNode;map.put(head, newNode);temp = newNode; head = head.next;}head = recHead;temp = newHead.next;while(head != null){ //通过head找到random指向的旧节点,再用map找到与该旧节点对应的新节点temp.random = map.get(head.random);head = head.next;temp = temp.next;}return newHead.next;}
[53]代码
public int search(int[] nums, int target) {if(nums.length == 0) //特殊情况排除return 0;else if(nums.length == 1 && target == nums[0]){return 1;}else if(nums.length == 1 && target != nums[0]){return 0;}int lBoarder = 0, rBoarder = 0;int left = 0, right = nums.length - 1;while(left <= right){ //寻找左端点,遇到目标值后,不结束查找,而是right=mid-1继续查找左端点,直到left>right则可以认为目前right指向target子串的前一位。int mid = left + (right-left)/2;if(nums[mid] < target){left = mid + 1;}else if(nums[mid] >= target){right = mid - 1;lBoarder = right+1;}}left = 0;right = nums.length - 1;while(left <= right){ //寻找右端点int mid = left + (right-left)/2;if(nums[mid] > target){right = mid - 1;}else if(nums[mid] <= target){left = mid + 1;rBoarder = left-1;}}if(nums[lBoarder] == target && nums[rBoarder] == target) //目标值也可能不存在于数组中,对其加以判断return rBoarder - lBoarder + 1;else return 0;}