-
两数之和
目标值-当前值 是否在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[]{};
}
-
字母异位词分组
排序每个单词作为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());
}
-
最长连续序列
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;
}
-
移动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++;
}
}
-
盛水最多
双指针分别在左右两端,向中间移动较小的
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;
}
-
三数之和
排序,双指针向中间移动
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;
}
-
最长无重复字符串
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;
}