100

32 阅读1分钟
  1. 两数之和

目标值-当前值 是否在map中,没有的话将当前值放进map继续循环

public int[] twoSum(int[] nums, int target) {
        if (nums.length < 2) {
            return new int[]{};
        }
        Map<Integer, Integer> map = new HashMap();
        for (int i = 0; i < nums.length; i++) {
            if (map.containsKey(target - nums[i])){
                return new int[]{i, map.get(target - nums[i])};
            }
            map.put(nums[i], i);
        }
        return new int[]{};
    }
  1. 字母异位词分组

排序每个单词作为key,value为源单词组成的列表

    public List<List<String>> groupAnagrams(String[] strs) {
        if (strs == null || strs.length == 0) {
            return new ArrayList<>();
        }
        Map<String, List<String>> map = new HashMap<>();
        for (String str : strs) {
            char[] chars = str.toCharArray();
            Arrays.sort(chars);
            String charsSorted = new String(chars);
            List<String> valueList = map.getOrDefault(charsSorted, new ArrayList<>());
            valueList.add(str);
            map.put(charsSorted, valueList);
        }
        return new ArrayList<>(map.values());
    }
  1. 最长连续序列

HashSet去重;遍历,有i-1(是:跳过;否:长度=1);while(i+1)长度++;maxLength = currentLength;

public int longestConsecutive(int[] nums) {
    HashSet<Integer> set = new HashSet<>();
    for (int num : nums) {
        set.add(num);
    }
    int maxLength = 0,currentLength = 0;
    for (Integer i : set) {
        if (set.contains(i-1)) {
            continue;
        }
        currentLength = 1;
        while (set.contains(i+1)) {
            i++;
            currentLength++;
        }
        if (currentLength > maxLength) {
            maxLength = currentLength;
        }
    }
    return maxLength;
}
  1. 移动0到末尾

左右指针都指向第一个;右不为0->左右交换 左++;右++(实际:左移非0)

public void moveZeroes(int[] nums) {
        int left = 0, right = 0, temp;
        while (right < nums.length) {
            if (nums[right] != 0) {
//            swap
                temp = nums[left];
                nums[left] = nums[right];
                nums[right] = temp;
                left++;
            }
            right++;
        }
    }
  1. 盛水最多

双指针分别在左右两端,向中间移动较小的

public int maxArea(int[] height) {
    int left = 0, right = height.length - 1, maxArea = 0;
    while (left < right) {
        int area = (right - left) * Math.min(height[left], height[right]);
        maxArea = Math.max(area, maxArea);
        if (height[left] > height[right]) {
            right--;
        } else {
            left++;
        }
    }
    return maxArea;
}
  1. 三数之和

排序,双指针向中间移动

public List<List<Integer>> threeSum(int[] nums) {
    List<List<Integer>> sum = new ArrayList<>();
    Arrays.sort(nums);
    int length = nums.length;
    //1.for循环左指针
    for (int left = 0; left < length - 2; left++) {
        if (left > 0 && nums[left] == nums[left - 1]) {
            continue;
        }
        //2.mid、right初始化,然后while循环他俩,++ --
        int mid = left + 1, right = length - 1;
        while (mid < right) {
            int target = nums[left] + nums[mid] + nums[right];
            if (target == 0) {
                List<Integer> list = new ArrayList<>();
                list.add(nums[left]);
                list.add(nums[mid]);
                list.add(nums[right]);
                sum.add(list);
                //去重
                while (mid < right && nums[mid] == nums[mid + 1]) {
                    mid++;
                }
                while (mid < right && nums[right] == nums[right - 1]) {
                    right--;
                }
                mid++;
                right--;
            } else if (target < 0) {
                mid++;
            } else {
                right--;
            }
        }
    }
    return sum;
}
  1. 最长无重复字符串

HashMap记录元素最后出现的位置,遍历字符串,当前元素到他前一个所在的位置的距离 取最大值,最后一个要特别处理下

public int lengthOfLongestSubstring(String s) {
//         哈希表记录元素最后出现的位置
        Map<Character, Integer> map = new HashMap<>();
        int distance = 0;//距离差
        int left = 0;//当前元素前一个位置
        int i;
        for (i = 0; i < s.length(); i++) {
            char currentChar = s.charAt(i);
            distance = Math.max(distance, i - left);//i - left:当前元素到他前一个所在的位置 距离
            Integer v = map.get(currentChar);
            left = (v != null) ? Math.max(left, v + 1) : left;
            map.put(currentChar, i);
        }
        return Math.max(distance, i - left);//最后一个元素到他上次出现的位置的差值 取大
    }

438. 找到字符串中所有字母异位词

滑动窗口:先把异常情况处理了,再处理第0个,然后滑动,字母计数先去掉已滑动过的(sCounts[s.charAt(i) - 'a']--;//前面的不要了),再加上当前滑动的那个(sCounts[s.charAt(i+pLen) - 'a']++;//后面的第一个要)

class Solution {
        public List<Integer> findAnagrams(String s, String p) {
        //1.处理p更长的情况,返回null
        int sLen = s.length(), pLen = p.length();
            if (sLen < pLen) {
                return new ArrayList<>();
            }

            List<Integer> result = new ArrayList<>();
            //2.计算前pLen个索引 s,p中26个字母的分别数量
            int[] sCounts = new int[26];
            int[] pCounts = new int[26];
            for (int i = 0; i < pLen; i++) {
                sCounts[s.charAt(i) - 'a']++;
                pCounts[p.charAt(i) - 'a']++;
            }
            if (Arrays.equals(sCounts, pCounts)) {
                result.add(0);
            }
            //3.处理剩余,每个字母的总数相同的情况
            for (int i = 0; i < sLen-pLen; i++) {
                sCounts[s.charAt(i) - 'a']--;//前面的不要了
                sCounts[s.charAt(i+pLen) - 'a']++;//后面的第一个要
                if (Arrays.equals(sCounts, pCounts)) {
                    result.add(i+1);
                }
            }
            return result;
        }
    }

160. 相交链表

双指针PA、PB分别从headA、headB开始遍历自己的链表,next为null时(自己的走完了),PA = headB PB=headA,此刻开始判断是否相等——走完自己的路走对方的,利用走同等距离两者相同来判断

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) {
            return null;
        }
        ListNode pA = headA, pB = headB;
        while(pA != pB) {
            pA = pA == null ? headB : pA.next;
            pB = pB == null ? headA: pB.next;
        }
        return pA;
    }
}

206. 反转链表

头插法:将原始链表的每个节点切断,将当前节点插入结果的头(how:当前链表仅一个节点,结果的next给这个节点)

public ListNode reverseList(ListNode head) {
    ListNode newHead = null;
    while (head != null) {
        ListNode next = head.next;//断开
        head.next = newHead;//当前节点插入到结果的头上(how:结果给当前节点的next)
        newHead = head;//赋值还给结果
        head = next;//遍历
    }
    return newHead;
}

234. 回文链表

栈。全部入栈,出栈和从头开始对比,有不相等的就false,否则true

public boolean isPalindrome(ListNode head) {
 if (head == null || head.next == null) {
     return true;
 }
 Stack<Integer> stack = new Stack<>();
 ListNode curr = head;
 while (curr != null) {//全部入栈
     stack.push(curr.val);
     curr = curr.next;
 }
 curr = head;//从头开始
 while (curr != null) {
     if (stack.pop() != curr.val) {
         return false;//出栈,如果有不相等的就false
     }
     curr = curr.next;
 }
 return true;
}

141. 环形链表

用HashSet存储ListNode,判断有无包含

public boolean hasCycle(ListNode head) {
            if (head == null) {
                return false;
            }
            Set<ListNode> set = new HashSet<>();
            while(head.next != null) {
                if (set.contains(head)) {
                    return true;
                }
                set.add(head);
                head = head.next;
            }
            return false;
        }