刷题记录|目标101题--双指针

写在前面

开个贴记录一下刷题的过程,目前参照leetcode101,目标101题,由于太久没写java了,也会涉及到一些java的基础用法,希望能和大家共勉吧~
已刷链接:

双指针


No.1 Two Sum II - Input Array Is Sorted

题目链接:https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/

设计到的算法:双指针
解题思路:左右各一个指针滑动既可
class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int i = 0, j = numbers.length - 1;
        while(numbers[i] + numbers[j] != target) {
            if (numbers[i] + numbers[j] < target) {
                i ++;
            } else {
                j --;
            }
        }
        int[] result = {++i,++j};
        return result;
    }
}

No.2 Merge Sorted Array

题目链接:https://leetcode.com/problems/merge-sorted-array/

涉及到的算法:双指针
解题思路:
从前往后的两个指针不可行因为会覆盖,那么考虑从后往前数两个指针,发现从后往前是work的

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int i = m - 1, j = n - 1, current = m + n - 1;
        while (i >= 0 && j >= 0) {
            if (nums1[i] > nums2[j]) {
                nums1[current--] = nums1[i--];
            } else {
                nums1[current--] = nums2[j--];
            }
        }
        while(i >= 0) {
            nums1[current--] = nums1[i--];
        }
        while(j >= 0) {
            nums1[current--] = nums2[j--];
        }
    }
}

No. 3 Linked List Cycle II

题目链接:https://leetcode.com/problems/linked-list-cycle-ii/

涉及到的算法:快慢指针
解题思路:快慢指针

快慢指针中如果用图表示就是将路径分为abc三段,a表示从链表头到成环点,b表示从环点到相遇处,c表示从相遇处到环点,其计算公式如下(图好丑TT)

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null) return null;
        ListNode fast = head;
        ListNode slow = head;
        while (fast.next != null && fast.next.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                break;
            }
        }
        if (fast.next == null || fast.next.next == null) {
            return null;
        }
        fast = head;
        while (slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }
        return slow;
    }
    
}

No.4 Minimum Window Substring

题目链接:https://leetcode.com/problems/minimum-window-substring/

涉及到的算法:滑动窗口
解题思路:
首先需要先遍历一遍string t,用数组记录下来他的character出现的次数。
用l和r指针遍历这个数组,在遍历时及时更新这个数组。
  • 如果r滑过了则将对应character次数--,
  • 如果l滑过了,此时如果只是单一的character数组,我们在看到l指针指向的字符对应在character数组中的计数为0时,无法区分是这个字符从未在string t中出现过,可以划走还是出现过但是正好被指针r覆盖,所以展示的0,此时不能划走,故引入数组flag[]在首次遍历时同时记录数组character和数组flag
  • 需要将string s从头到位遍历一遍,存储一个最小值,中间每次满足条件时将值与最小值对比,如果比最小值还要小更新最小值

  • 涉及到的java原理:
class Solution {
    public String minWindow(String s, String t) {
        if (t.length() > s.length()) return "";
        int[] characters = new int[128];
        boolean[] flag = new boolean[128];
        for (int i = 0; i < t.length(); i++) {
            int index = t.charAt(i);
            flag[index] = true;
            characters[index]++;
        }
        int begin_index = 0, end_index = s.length(),count = 0;
        for (int r = 0,l = 0; r < s.length(); r++) {
            int indexR = s.charAt(r);
            if (flag[indexR] && characters[indexR]-- > 0) {
                count++;
            }
            while (count == t.length()) {
                int indexL = s.charAt(l);
                if (flag[indexL] && ++characters[indexL] > 0) {
                    if (r-l+1 <  end_index-begin_index +1) {
                        begin_index = l;
                        end_index = r;
                    }
                    count--;
                }
                l++;
            }
        }
        return end_index == s.length() ? "" : s.substring(begin_index,end_index+1);
    }
}

No.5 Sum of Square Numbers

题目链接:https://leetcode.com/problems/sum-of-square-numbers/

涉及到的算法:双指针
解题思路:
Two Sum 变种
这里需要注意两点:
  1. 不能将r=c/2,而要使用java的开根号方法double Math.sqrt(),向下取整,防止溢出
  2. 因为 0 <= c && c <= 231 - 1,我们在计算时如果使用 a2 + b2 容易溢出,可以使用 c - a2 的形式去判断,就不会溢出了
class Solution {
    public boolean judgeSquareSum(int c) {
        if (c <= 2) return true;
        int l = 0, r = (int)(Math.sqrt(c));
        while(l <= r) {
            int left = l * l;
            int right = c - left;
            if (right == r * r) {
                return true;
            } else if (right < r * r) {
                r --;
            } else {
                l ++;
            }
        }
        return false;
    }
}

No.6 Valid Palindrome II

题目链接:https://leetcode.com/problems/valid-palindrome-ii/

涉及到的算法:双指针
解题思路:左右各一个指针,遇见不同时尝试跳过左边的数字和跳过右边的数字两种情况就可以。
class Solution {
    public boolean validPalindrome(String s) {
        int l = 0, r = s.length() - 1;
        while (l < r && s.charAt(l) == s.charAt(r)) {
            l++;r--;
        }
        if (s.charAt(l) == s.charAt(r)) return true;
        return isPalindrome(s.substring(l + 1,r + 1)) || isPalindrome(s.substring(l,r));
    }
    private boolean isPalindrome(String s) {
        int l = 0, r = s.length() - 1;
        while (l < r && s.charAt(l) == s.charAt(r)) {
            l++;r--;
        }
        if (s.charAt(l) == s.charAt(r)) return true;
        return false;
    }
}

No.7 Longest Word in Dictionary through Deleting

题目链接:https://leetcode.com/problems/longest-word-in-dictionary-through-deleting/

涉及到的算法:双指针
解题思路:
先给 dictionary 排序,排完以后就是一个简单的对比string的问题
class Solution {
    public String findLongestWord(String s, List<String> dictionary) {
        Collections.sort(dictionary,(a,b) -> {
            if (a.length() != b.length()) {
                return b.length() - a.length();
            } 
            for (int i = 0; i < a.length(); i++) {
                if (a.charAt(i) != b.charAt(i)) {
                     return a.charAt(i) - b.charAt(i);
                }
            }
            return 0;
        });
        for(int i = 0; i < dictionary.size();i++) {
            if (dictionary.get(i).length() > s.length()) {
                continue;
            }
            String target = dictionary.get(i);
            int j = 0,k = 0;
            for(; j < s.length() && k < target.length(); j++) {
                if (s.charAt(j) == target.charAt(k)) {
                    k++;
                }
            }
            if (k == target.length()) {
                return target;
            }
        }
        return "";
    }
}

No. 8 Longest Substring with At Most K Distinct Characters

本题需要leetcode会员,贫穷的我选择直接看好心人的题解T T:https://aaronice.gitbook.io/lintcode/two_pointers/longest_substring_with_at_most_k_distinct_characters
涉及到的java知识:
题目:
解题思路:
求一个最长的substring的length,可以知道我们的思路是采用一个双指针的滑动窗口,在滑动的过程中去更新这个length,生息的问题是如何去维护这个滑动窗口。
我们要能确定这个这个substring的窗口中有几种字符需要额外开辟一块存储空间,去存储在这个窗口中哪些字符出现了,出现了几次。
我们需要获取在这个窗口中出现的distinct character的数量,但是数组无法确定究竟有哪些不同的character被存入,所以我们要换用可以直接获得size的hashmap进行储存,开辟一块存储,存储对应character出现次数的index
如何滑动:
设置一个左指针firstIndex 一个右指针endInex表示滑动窗口的起始与结尾,每次将endInex右++,将其指向的character存入hashMap,如果曾经有就将其次数++;
如果此时hashMap的size已经大于k了,就可以开始移动左指针firstIndex,进行删除操作,直到size不再大于k;
每次移动右指针时更新最长的值,最后返回记录的最长的值
#力扣刷题##逃离互联网#
全部评论

相关推荐

1 收藏 评论
分享
牛客网
牛客企业服务