Zzahozhao的刷算法之路-第三周

75 阅读4分钟

每周一句:万物自有节奏,忙有价值,闲有滋味。

5.3.反转链表

  1. 题目:给定单链表的头节点 head ,请反转链表,并返回反转后的链表的头节点。

  2. 示例:

    示例 1:
    输入:head = [1,2,3,4,5]
    输出:[5,4,3,2,1]
    ​
    示例 2:
    输入:head = [1,2]
    输出:[2,1]
    ​
    示例 3:
    输入:head = []
    输出:[]
  3. 思路:

    1. 双指针定义两个指针,遍历进行交换
    2. 递归
  4. 代码实现

       if(head == null || head.next == null){
                return head;
            }
    ​
            ListNode cur = head;
            ListNode pre = null;
            while(cur != null){
                ListNode temp = cur.next;
                cur.next = pre;
                pre = cur;
                cur = temp;
            }
    ​
            return pre;
        }
    ​
    ​
    class Solution {
        public ListNode reverseList(ListNode head) {
            if(head == null || head.next == null){
                return head;
            }
            return reverse(head,null);
        }
    ​
        public ListNode reverse(ListNode cur, ListNode pre){
            if(cur == null){
                return pre;
            }
    ​
            ListNode temp = cur.next;
            cur.next = pre;
            return  reverse(temp,cur);
        }
    }
    

5.4.两两交换链表

  1. 题目:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

  2. 示例:

    示例 1:
    输入:head = [1,2,3,4]
    输出:[2,1,4,3]
    ​
    示例 2:
    输入:head = []
    输出:[]
    ​
    示例 3:
    输入:head = [1]
    输出:[1]
    
  3. 思路:

    1. 定义虚拟头节点
    2. 创建指针指向虚拟头节点,在交换,然后移动cur节点到要交换链表的前一个节点再次进行交换
  4. 代码:

    class Solution {
        public ListNode swapPairs(ListNode head) {
            if(head == null || head.next == null){
                return head;
            }
    ​
            ListNode dummHead = new ListNode(-1);
            dummHead.next = head;
            ListNode cur = dummHead;
    ​
            while(cur.next != null && cur.next.next != null){
                ListNode temp = cur.next.next.next;
                ListNode temp1 = cur.next;
                cur.next = cur.next.next;
                cur.next.next = temp1;
                temp1.next = temp;
                cur = cur.next.next;
            }
            return dummHead.next;
        }
    }
    

5.5.删除链表的倒数第 N 个结点

  1. 题目:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

  2. 示例:

    示例 1:
    输入:head = [1,2,3,4,5], n = 2
    输出:[1,2,3,5]
    ​
    示例 2:
    输入:head = [1], n = 1
    输出:[]
    ​
    示例 3:
    输入:head = [1,2], n = 1
    输出:[1]
    
  3. 思路:

    1. 创建虚拟头节点来操作
    2. 创建快慢指针,让快指针先走n步,快慢指针再一起走
    3. 直到快指针到了链表尾部,让慢指针所在的节点只想下下个节点
  4. 代码

    class Solution {
        public ListNode removeNthFromEnd(ListNode head, int n) {
           ListNode dummyHead = new ListNode(-1);
            dummyHead.next = head;
    ​
            ListNode fast = dummyHead;
            ListNode slow = dummyHead;
    ​
            while(n+1 != 0){
                fast = fast.next;
                n--;
            }
    ​
            while(fast != null){
                fast = fast.next;
                slow = slow.next;
            }
    ​
            slow.next = slow.next.next;
            return dummyHead.next;
        }
    }
    

哈希表

6.1.有效的字母异位词

  1. 题目:

  2. 给定两个字符串 *s**t* ,编写一个函数来判断 *t* 是否是 *s* 的字母异位词。

    注意:*s**t* 中每个字符出现的次数都相同,则称 *s**t* 互为字母异位词。

  3. 示例

    示例 1:
    输入: s = "anagram", t = "nagaram"
    输出: true
    ​
    示例 2:
    输入: s = "rat", t = "car"
    输出: false
    
  4. 思路

    1. 利用数组来求解,因为只有26个字母所以先创建一个数组大小为26的数组
    2. 又因为字母的相减是数值,我们只需要让每个字符去减去字母a就可以得到字母对应为位置,因为字母的ASCII是递增的,所以用所有的字母减去a就会得到对应的位置
    3. 找到位置后++,然后再操作另一个但是是减减
    4. 只要数组没有!=0就为异位词
  5. 代码

    class Solution {
        public boolean isAnagram(String s, String t) {
            if(s.length() != t.length()){
                return false;
            }
    ​
            int[] arr = new int[26];
    ​
            for(int i = 0; i < s.length(); i++){
                arr[s.charAt(i) - 'a']++;
            }
    ​
            for(int i = 0; i < t.length(); i++){
                arr[t.charAt(i) - 'a']--;
            }
    ​
            for(int i : arr){
                if(i != 0){
                    return false;
                }
            }
    ​
            return true;
        }
    }
    

6.2.两个数组的交集

  1. 题目:给定两个数组 nums1nums2 ,返回 它们的 交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序

  2. 示例:

    示例 1:
    输入:nums1 = [1,2,2,1], nums2 = [2,2]
    输出:[2]
    示例 2:
    输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
    输出:[9,4]
    解释:[4,9] 也是可通过的
    
  3. 思路

    1. 先将第一个数组存到hash里面
    2. 创建个新的判断hash中是否包含第二个数组的值,包含直接放入新的hash里面
  4. 代码

    class Solution {
        public int[] intersection(int[] nums1, int[] nums2) {
            HashMap<Integer, Integer> map = new HashMap<>();
    ​
            Arrays.stream(nums1).forEach(n ->map.put(n,n));
            Set<Integer> objects = new HashSet<Integer>(){
            };
            for (int i : nums2) {
                if(map.containsKey(i)){
                    objects.add(map.get(i));
                }
            }
            return objects.stream().mapToInt(x -> x).toArray();
        }
    }