代码随想录复习 Day1 - Day7

Day1|你就像一道二分查找

Leetcode704.二分查找

使用前提:有序数组

本质:根据是否满足题目条件来缩小答案的区间

fast

数组中移除元素并不容易! | LeetCode:27. 移除元素哔哩哔哩bilibili

Day2|977.有序数组的平方 209.长度最小的子数组 59.螺旋矩阵II

滑动窗口的本质上是满足了单调性,when sum >= target,左指针右移,再检查此区间内是否仍>=target,以此来找到最小区间

螺旋矩阵:offset的意义在于结束一圈后,起始位置向后,结束位置向前移

Day3|移除链表|设计链表|反转链表

移除链表元素

1.要把哪个元素排除出元素,只需要使得没有指向它的指针,如果cur指向2那么只能更改2的next指针

2.链表首先要想好指针式怎么移动的,是否会访问null

设计链表

自己打一下好了

//细节点还是比较多的
class MyLinkedList {
    int size;
    ListNode head;
​
    public MyLinkedList() {
    size = 0;
    head = new ListNode(0);
    }
    
    public int get(int index) {
    if(index<0||index>=size){
        return -1;
    }
    ListNode cur = head;//cur指向的是虚拟头节点
    for(int i = 0;i<=index;i++)
    {//因为设置了虚拟头结点,就需要跳两次
     cur = cur.next;
    }
    return cur.val;
    }
    
    public void addAtHead(int val) {
    addAtIndex(0,val);
    }
    
    public void addAtTail(int val) {
     addAtIndex(size,val);
    }
    
    public void addAtIndex(int index, int val) {
    if(index>size){
        return ;
    }
    if(index<0){
        index = 0;
    }
    size++;
    ListNode pre = head;
    for(int i = 0;i<index;i++)
    {
    pre = pre.next;
    }
    ListNode newNode = new ListNode(val);
    newNode.next = pre.next;
    pre.next = newNode;
    }
    
    public void deleteAtIndex(int index) {
    if(index<0||index>=size){
        return;
    }
    size--;
    ListNode pre = head;
    //同样也是找前驱
    for(int i = 0;i<index;i++){
        pre = pre.next;
    }
    pre.next = pre.next.next;
    }
}
​
/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList obj = new MyLinkedList();
 * int param_1 = obj.get(index);
 * obj.addAtHead(val);
 * obj.addAtTail(val);
 * obj.addAtIndex(index,val);
 * obj.deleteAtIndex(index);
 */

反转链表

DAY4| 24. 两两交换链表中的节点 |19.删除链表的倒数第N个节点 |面试题 02.07. 链表相交 |142.环形链表II

两两交换链表中的结点

while(pre.next!=null && pre.next.next != null){
    //奇数结点最后一个不需要交换
}

Day6| 242.有效的字母异位词 |349两个数组的交集 |202快乐数|1.两数之和

两个数组的交集

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
 if(nums1 == null || nums1.length == 0
 ||nums2 == null || nums2.length == 0){
     return new int[0];
 }
 Set<Integer> set1 = new HashSet<>()
 Set<Integer> resSet = new HashSet<>();
​
 //遍历数组1
 for(int i:nums1){
     set1.add(i);//可以去重
 }
 for(int i:nums2){
     if(set1.contains(i)){
         resSet.add(i);//如果元素i在nums1 and nums2 都有,就加入
     }
 }
 return resSet.stream().mapToInt(x->x).toArray();
​
    }
}

快乐数

class Solution {
    public boolean isHappy(int n) {
   int temp = getSum(n);
   Set<Integer> set = new HashSet<>();
   while(temp!=1){
       if(!set.contains(temp)){
           //如果还不是快乐数,并且在快乐数的循环中还没有出现重复的值
           set.add(temp);
           //加入此次探索中出现的数
       }
       else{//如果出现重复的值,那就说明陷入了无限循环
           return false;
       }
       temp = getSum(temp);
       return true;
   }
    }
    public int getSum(int n){
        int sum = 0;
        while(n!=0){
            sum += (int)Math.pow(n%10,2);
            n = n/10;//退位
        }
        return sum;
    }
}

两数之和

 class Solution {
    public int[] twoSum(int[] nums, int target) {
      Map<Integer,Integer> map = new HashMap<>();
      int[] res = new int[2];
      for(int i = 0;i<nums.length;i++){
          int temp = target-nums[i];
​
        if(map.containsKey(temp)){
            res[0] = map.get(temp);
            res[1] = i;
            break;//找到了就直接结束遍历搜索了
        }
        map.put(nums[i],i);
      }
      return res;
    }
}
Day7| 454.四数相加II |384赎金信 |15.三数之和 |18四数之和

四数之和

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
    int res= 0;
    HashMap<Integer,Integer> map = new HashMap<>();
    for(int i:nums1){
        for(int j:nums2){
            int sum = i+j;
            map.put(sum,map.getOrDefault(sum,0)+1);
            //如果找到了,就会返回sum的次数
            //map.put(sum,value),value是sum出现的次数
        }
    }
    for(int i:nums3){
        for(int j:nums4){
            int sum =  i+j;
            res += map.getOrDefault(-sum,0);
        }
    }
    return res;
    }
}

赎金信

​
class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        int[] a = new int[26];
        for(int i = 0;i<ransomNote.length();i++){
            a[ransomNote.charAt(i)-'a']++;
        }//将ransomNote中的字母的数量存储起来
        for(int i = 0;i<magazine.length();i++){
            if(a[magazine.charAt(i)-'a']==0) continue;
            a[magazine.charAt(i)-'a']--;
            //遍历magazine中所有的字母,如果数组不为0,说明ransmNote同样具备,这个时候就可以对应消除掉
        }
        for(int i = 0 ;i<26;i++){
            if(a[i]!=0) return false;
        }
        return true;
    }
}

三数之和

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
   List<List<Integer>> result = new ArrayList<>();
   Arrays.sort(nums);
​
   for(int i = 0;i<nums.length;i++){
       if(nums[i]>0){
           return result;
       }
​
       if(i>0&&nums[i] == nums[i-1]){
           continue;
       }
       int left = i+1;
       int right = nums.length-1;
       while(right>left){
           int sum = nums[i]+nums[left]+nums[right];
           if(sum>0){
               right--;
           }else if(sum<0){
               left++;
           }else{
               result.add(Arrays.asList(nums[i],nums[left],nums[right]));
               //前面都是对a去重,再找到一个三元组后,对b和c进行去重
               while(right>left && nums[right] == nums[right-1]) right--;
               while(right>left && nums[left] == nums[left+1]) left++;
               right--;
               left++;
           }
       }
   }
   return result;
    }
}

四数之和

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
   List<List<Integer>> res = new ArrayList<>();
   Arrays.sort(nums);
   for(int k = 0;k<nums.length;k++){
       if(nums[k]>target && target>0) break;
       //因为是从小到大排序,如果一个数已经大于target了,那么就没有必要往后面进行探索了
       if(k>0&&nums[k]==nums[k-1]) continue;
       //去重
       //与三重还是有联系的,都是先确定初始位置
       for(int i = k+1;i<nums.length;i++){
           if(i>k+1 && nums[i] ==  nums[i-1]) continue;//这里也是去重操作
           int temp =  nums[k]+nums[i];
           int left = i+1;
           int right = nums.length-1;
           while(left<right){
               long sum = (long)nums[left] + nums[right] + temp;
               if(sum>target){
                   right--;
               }
               else if(sum<target){
                   left++;
               }
               else{
                   res.add(Arrays.asList(nums[k],nums[i],nums[left],nums[right]));
                   //每次确定一个四重组合,又要对c,d去重
                   while(left<right && nums[left] == nums[left+1]) left++;
                   while(left<right&&nums[right] == nums[right-1]) right--;
                   left++;
                   right--;
                   //去完重之后,还是需要移动,因为前面的代码并没有移动
               }
           }
       }
   }
   return res;
    }
}

6.25 还是想要复习一下二叉树

Java中TreeNode通常是由自己定义的类实现的,用于表示二叉树的节点。具体来说,可以将TreeNode定义为一个包含value、left子节点和right子节点三个成员变量的类。其中value可以是任何类型,left和right则是指向另外两个TreeNode对象的引用。

下面是一个简单的样例,用于展示TreeNode的定义和使用:

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}
​
public class Solution {
    public static void main(String[] args) {
        // 创建一棵二叉树
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(3);
        root.left.left = new TreeNode(4);
        root.left.right = new TreeNode(5);
​
        // 遍历二叉树
        System.out.println("Preorder traversal: ");
        preorderTraversal(root);
        System.out.println("\nInorder traversal: ");
        inorderTraversal(root);
        System.out.println("\nPostorder traversal: ");
        postorderTraversal(root);
    }
​
    // 前序遍历
    public static void preorderTraversal(TreeNode root) {
        if (root == null) {
            return;
        }
        System.out.print(root.val + " ");
        preorderTraversal(root.left);
        preorderTraversal(root.right);
    }
​
    // 中序遍历
    public static void inorderTraversal(TreeNode root) {
        if (root == null) {
            return;
        }
        inorderTraversal(root.left);
        System.out.print(root.val + " ");
        inorderTraversal(root.right);
    }
​
    // 后序遍历
    public static void postorderTraversal(TreeNode root) {
        if (root == null) {
            return;
        }
        postorderTraversal(root.left);
        postorderTraversal(root.right);
        System.out.print(root.val + " ");
    }
}

在这个示例中,我们定义了一个TreeNode类用于表示二叉树的节点,然后创建了一棵二叉树。最后,我们使用前序、中序和后序遍历算法打印出了这棵二叉树的节点值。

中序遍历

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> res = new LinkedList<>();
    Stack<TreeNode> st = new Stack<>();
    if(root!=null){
         st.push(root);
    }
    while(!st.isEmpty()){
        TreeNode node = st.peek();
        if(node!=null){
            st.pop();//node已经指向中顶元素了
            if(node.right!=null){
                st.push(node.right);
            }
            st.push(node);
            st.push(null);
            if(node.left!=null){
                st.push(node.left);
            }//如果这一步没有了,null的作用就正式开始,后面就会将stack中的值依次放入res数组中
        }
        else{//到了这一步就是到了最左子节点
            st.pop();//将null去去除
            node = st.peek();
            st.pop();//每次取了peek的值都是要pop掉的
            res.add(node.val);
        }
    }
    return res;  
    }
}
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> res = new LinkedList<>();
    Stack<TreeNode> st = new Stack<>();
    if(root!=null){
        st.push(root);
    }
    while(!st.isEmpty()){
        TreeNode node = st.peek();
        if(node!=null) // 就开始右中左的入栈顺序
        {
            st.pop();//每次peek一个都要即时pop()
            if(node.right!=null){
                st.push(node.right);
            }
            st.push(node);
            st.push(null);
            if(node.left!=null){
                st.push(node.left);
            }
        }
        else{
            st.pop();
            node = st.peek();
            res.add(node.val);
            st.pop();
        }
    }
    return res;
    }
}
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> res = new ArrayList<>();
    if(root == null){
        return res;
    }
    Stack<TreeNode> st = new Stack<>();
    //注意在开始的时候是不需要加root的
    TreeNode cur = root;
    while(cur!=null || !st.isEmpty()){
        // cur !=nulll 是为了让我们顺利遍历到左子树最左子节点
        // st.isEmpty() 是为了将stack存到res中去的
        if(cur !=null){//cur承担遍历到最左子节点的作用,最初的结点也算是一个左节点
            st.push(cur);
            cur = cur.left;
        }
        else{
            cur = st.pop();//cur承担了最后栈转换到res的中转站
            res.add(cur.val);
            cur = cur.right;
        }
    }
    return res;
    }
}

后序遍历

入栈顺序:中左右//代码是这个

出栈顺序:中右左

倒转:左右中

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
    List<Integer> res = new ArrayList<>();
    if(root == null){
        return res;
    }
    Stack<TreeNode> st = new Stack<>();
    st.push(root);
    while(!st.isEmpty()){
        TreeNode cur = st.pop();
        res.add(cur.val);
        if(cur.left!=null){
           st.push(cur.left);
        }
        if(cur.right!=null){
        st.push(cur.right);
        }
    }
    Collections.reverse(res);
    return res;
    }
}
二叉树的层序遍历
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    private List<List<Integer>> resList = new ArrayList<>();
    public List<List<Integer>> levelOrder(TreeNode root) {
    travelsal(root,0);
    return resList;
    }
    private void travelsal(TreeNode root,int deep)
    {
        //第一部先判断是否为叶子节点
        if(root == null) return;
        //如果不是,则就是新的一层,需要加一层深度
        deep++;
        //加了一层深度,也就意味着需要加一个List<>来储存这一层叶节点的值
        //当然只有第一次,也就是最左边结点遍历的时候才会需要去加一个List<>
        if(resList.size()<deep){
            List<Integer> temp = new ArrayList<>();
            resList.add(temp);
        }
        //实际操作的时候,deep-1 才是当前层
        resList.get(deep-1).add(root.val);

        travelsal(root.left,deep);
        travelsal(root.right,deep);
    }
}

感觉层序遍历那里真的有点多了,没有必要,后面还是要过的

翻转二叉树
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode invertTree(TreeNode root) {
    //递归写法
    //1.确定终止条件
    if(root == null){
        return null;
    }
    //先交换左右孩子结点,然后反转右孩子结点
    //然后反转左子树,反转右子树
    //我们可以发现这两步其实就是从小看大
    invertTree(root.left);
    invertTree(root.right);
    swap(root);
    return root;
    }
    private void swap(TreeNode node){
        TreeNode temp = node.left;
        node.left = node.right;
        node.right = temp;
    } 
}
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode invertTree(TreeNode root) {
   //迭代法就是从头到脚遍历
   if(root == null) return null;
   Deque<TreeNode> que = new ArrayDeque<>();
   que.offer(root);
   while(!que.isEmpty()){
       int size = que.size();
       for(int i = 0;i<size;i++){
           TreeNode node = que.poll();
           swap(node);//先将头节点的左右子树进行更换
           if(node.left!=null) que.offer(node.left);
           if(node.right!=null) que.offer(node.right);//这里是按照队列的规矩办事
       }
   }
   return root;
    }
    private void swap(TreeNode node){
        TreeNode tmp = node.left;
        node.left = node.right;
        node.right = tmp;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值