每日刷题->链表+树+栈+队列+数组

1.链表中倒数第k个节点->快慢指针

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode getKthFromEnd(ListNode head, int k) {
        ListNode slow=head,fast=head;
        while(k>0){
            fast=fast.next;
            k--;
        }
        while(fast!=null){
            fast=fast.next;
            slow=slow.next;
        }
        return slow;
    }
}

2.反转链表->pre,cur,next

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre=null,cur=head,next=null;
        while(cur!=null){
            next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=next;
        }
        return pre;
    }
}

3.合并两个排序的链表->逐个节点比较

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1==null) return l2;
        if(l2==null) return l1;
        ListNode dummyHead=new ListNode(0);//创建一个假头,就可以省略头部的比较
        ListNode cur=dummyHead;
        while(l1!=null && l2!=null){
            if(l1.val<l2.val){
                cur.next=l1;
                cur=cur.next;
                l1=l1.next;
            }else{
                cur.next=l2;
                cur=cur.next;
                l2=l2.next;
            }
        }
        if(l1!=null){
            cur.next=l1;
        }
        if(l2!=null){
            cur.next=l2;
        }
        return dummyHead.next;
    }
}

4.树的子结构->递归

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSubStructure(TreeNode A, TreeNode B) {
        if(A==null || B==null){
            return false;
        }
        //如果A和B不一致,再去遍历A的左右子树,看和B是否有一致的
        return dfs(A,B) || isSubStructure(A.left,B) || isSubStructure(A.right,B);
    }
    //遍历树A和B,看是否一致
    public boolean dfs(TreeNode A,TreeNode B){
        if(B==null) return true;//B可以为空,这时候可以是B已经遍历完了
        if(A==null) return false;//但是在B不为空情况下,A不能为空,如果A为空,就不是子树
        return (A.val==B.val)&&dfs(A.left,B.left)&&dfs(A.right,B.right);
    }
}

5.二叉树的镜像->递归

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        //交换左右节点
        //特殊情况
        if(root==null || (root.left==null && root.right==null)){
            return root;
        }
        //应该自顶向下交换
        //(1)先交换当前节点的左右子节点
        TreeNode temp=null;
        temp=root.left;
        root.left=root.right;
        root.right=temp;
        //(2)再向下递归
        mirrorTree(root.left);
        mirrorTree(root.right);
        return root;
    }
}

6.对称的二叉树->递归

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root==null){
            return true;
        }
        return helper(root.left,root.right);
    }
    public boolean helper(TreeNode node1,TreeNode node2){
        if(node1==null && node2==null){
            return true;
        }
        if(node1==null || node2==null){
            return false;
        }
        return(node1.val==node2.val)&&helper(node1.left,node2.right)&&helper(node1.right,node2.left);
    }
}

7.顺时针打印矩阵->逻辑策略,边界条件

在这里插入图片描述

class Solution {
    public int[] spiralOrder(int[][] matrix) {
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return new int[0];//记住啊!!!
        }
        List<Integer> list=new ArrayList<>();
        int n=matrix.length;//行数
        int m=matrix[0].length;//列数
        int top=0,bottom=n-1,left=0,right=m-1;
        while(top<=bottom && left<=right){
            for(int j=left;j<=right;j++){//从左到右,包含最右边的元素
                list.add(matrix[top][j]);
            }
            for(int i=top+1;i<=bottom;i++){//从上到下,包含最下边的元素
                list.add(matrix[i][right]);
            }
            //只有当top<bottom && left<right时才需要向左及向上遍历
            //否则只有单行的话就不需要进行这两个遍历
            if(top<bottom && left<right){
                for(int j=right-1;j>left;j--){
                    list.add(matrix[bottom][j]);//从右到左,不包含最左边的元素
                }
                for(int i=bottom;i>top;i--){
                    list.add(matrix[i][left]);//从下到上,不包含最上边的元素
                }
            }
            top++;
            bottom--;
            left++;
            right--;
        }
        int[] res=new int[list.size()];
        for(int t=0;t<res.length;t++){
            res[t]=list.get(t);
        }
        return res;
    }
}

8.包含main函数的栈->栈

在这里插入图片描述

class MinStack {
    private Deque stackA;//数据栈
    private Deque stackB;//辅助栈,始终将最小值存放在栈顶
    /** initialize your data structure here. */
    public MinStack() {
        stackA=new LinkedList();
        stackB=new LinkedList();
    }
    
    public void push(int x) {
        stackA.push(x);
        //当栈B为空或者栈顶元素大于x时,将x放在B的栈顶
        if(stackB.isEmpty() || (int)stackB.peek()>=x){
            stackB.push(x);
        }
    }
    
    public void pop() {
        //如果Apop出去的元素和B栈顶元素相等,那么就是要把最小元素pop出去,所以B也要弹栈
        if((int)stackA.pop()==(int)stackB.peek()){
            stackB.pop();
        }
    }
    
    public int top() {
        return (int)stackA.peek();
    }
    
    public int min() {
        return (int)stackB.peek();
    }
}

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(x);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.min();
 */

9.栈的压入、弹出序列->栈

在这里插入图片描述

class Solution {
    public boolean validateStackSequences(int[] pushed, int[] popped) {
        //模拟压栈弹栈过程
        Deque<Integer> stack=new LinkedList<>();
        int i=0;//记录popped数组的索引位置
        for(int num:pushed){
            stack.push(num);
            while(!stack.isEmpty() && stack.peek()==popped[i]){
                stack.pop();
                i++;
            }
        }
        return stack.isEmpty();
    }
}

10.从上到下打印二叉树1->利用队列进行层序遍历

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int[] levelOrder(TreeNode root) {
        if(root==null){
            return new int[0];
        }
        //利用栈的先入先出特性解决
        //定义一个队列
        Queue<TreeNode> queue = new LinkedList<>();
        //将根节点入队列
        queue.offer(root);
        //定义一个list存储结果
        List<Integer> list=new ArrayList<>();
        while(!queue.isEmpty()){
            TreeNode node=queue.poll();
            list.add(node.val);
            if(node.left!=null){
                queue.offer(node.left);
            }
            if(node.right!=null){
                queue.offer(node.right);
            }
        }
        int[] res=new int[list.size()];
        for(int i=0;i<res.length;i++){
            res[i]=list.get(i);
        }   
        return res;   
    }
}

11.从上到下打印二叉树2->层序遍历,需记录层数

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    List<List<Integer>> res=new ArrayList();
    public List<List<Integer>> levelOrder(TreeNode root) {
        if(root==null) return res;
        helper(root,0);
        return res;
    }

    //定义一个辅助函数,需要记录层数,利用层数决定是否新开一个子数组
    public void helper(TreeNode root,int k){
        if(root!=null){
            //如果多了一层,就新建一个子数组
            if(res.size()<=k){
                res.add(new ArrayList<Integer>());
            }
            res.get(k).add(root.val);
            helper(root.left,k+1);
            helper(root.right,k+1);
        }
    }
}

12.从上到下打印二叉树2->层序遍历,需记录层数+判断层数奇偶

在这里插入图片描述

13二叉搜索树的后序遍历序列->二叉搜索树后续遍历性质

在这里插入图片描述

class Solution {
    public boolean verifyPostorder(int[] postorder) {
        int n=postorder.length-1;
        if(n==0)return true;
        return helper(postorder,0,n);
    }
    //二叉搜索树的后序遍历结果性质应该有,对于位置[i,j):
    //(1)最后一个值是根节点的值postorder[j-1]
    //(2)从左到右遍历,第一个大于postorder[j-1]的值是属于右子树的,记录它的索引是m
    //则左子树范围是[i,m-1],右子树范围是[m,j-1],根节点索引是m
    public boolean helper(int[] postorder,int i,int j){
        if(i>=j){
            return true;
        }
        int p=i;
        //从左到右找第一个大于根节点的节点,跳出循环的时候p指向的元素大于根节点的值
        while(postorder[p]<postorder[j]){
            p++;
        }
        int m=p;//第一个大于根节点的节点的位置
        //继续从左往右遍历,如果遇到小于根节点的值跳出循环,因为右子树中的所有值都应该大于根节点的值
        while(postorder[p]>postorder[j]){
            p++;
        }
        //递归遍历左右子树
        return (p==j)&&helper(postorder,i,m-1)&&helper(postorder,m,j-1);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值