leetcode -1
001 两数之和:map,一次遍历
class Solution { public int[] twoSum(int[] nums, int target) { Map<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int complement = target - nums[i]; if (map.containsKey(complement)) { return new int[] { map.get(complement), i }; } map.put(nums[i], i); } throw new IllegalArgumentException("No two sum solution"); } }
146 LRU缓存机制:LinkedHashMap 覆写removeEldestEntry;HashMap + 链表
//方法1:LinkedHashMap class LRUCache extends LinkedHashMap<Integer, Integer>{ private int capacity; public LRUCache(int capacity) { super(capacity, 0.75F, true); this.capacity = capacity; } public int get(int key) { return super.getOrDefault(key, -1); } public void put(int key, int value) { super.put(key, value); } @Override protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) { return size() > capacity; } } //方法2: public class LRUCache { class DLinkedNode { int key; int value; DLinkedNode prev; DLinkedNode next; public DLinkedNode() {} public DLinkedNode(int _key, int _value) {key = _key; value = _value;} } private Map<Integer, DLinkedNode> cache = new HashMap<Integer, DLinkedNode>(); private int size; private int capacity; private DLinkedNode head, tail; public LRUCache(int capacity) { this.size = 0; this.capacity = capacity; // 使用伪头部和伪尾部节点 head = new DLinkedNode(); tail = new DLinkedNode(); head.next = tail; tail.prev = head; } public int get(int key) { DLinkedNode node = cache.get(key); if (node == null) { return -1; } // 如果 key 存在,先通过哈希表定位,再移到头部 moveToHead(node); return node.value; } public void put(int key, int value) { DLinkedNode node = cache.get(key); if (node == null) { // 如果 key 不存在,创建一个新的节点 DLinkedNode newNode = new DLinkedNode(key, value); // 添加进哈希表 cache.put(key, newNode); // 添加至双向链表的头部 addToHead(newNode); ++size; if (size > capacity) { // 如果超出容量,删除双向链表的尾部节点 DLinkedNode tail = removeTail(); // 删除哈希表中对应的项 cache.remove(tail.key); --size; } } else { // 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部 node.value = value; moveToHead(node); } } private void addToHead(DLinkedNode node) { node.prev = head; node.next = head.next; head.next.prev = node; head.next = node; } private void removeNode(DLinkedNode node) { node.prev.next = node.next; node.next.prev = node.prev; } private void moveToHead(DLinkedNode node) { removeNode(node); addToHead(node); } private DLinkedNode removeTail() { DLinkedNode res = tail.prev; removeNode(res); return res; } }
004 寻找两个正序数组的中位数:Arrays.sort();…… ;
005 最长回文子串:中心扩散法,注意s.substring(left, right)表示包含left不包含right的子串
class Solution { public String longestPalindrome(String s) { int len = s.length(); String ans = ""; for (int i = 0; i < len; i++) { String odd = maxLengthPalidrome(s, i, i); String edd = maxLengthPalidrome(s, i, i + 1); String tmp = odd.length() > edd.length() ? odd : edd; ans = ans.length() > tmp.length() ? ans : tmp; } return ans; } private String maxLengthPalidrome(String s, int i, int j) { int left = i; int right = j; while (left >= 0 && right < s.length()) { if(s.charAt(left) == s.charAt(right)){ left--; right++; }else { break; } } return s.substring(left+1, right); } }
206 翻转链表:声明 pre=null, current= head, while(curr!=null){ tmp = curr.next; curr.next = pre; pre = current; current = tmp;} return prev;
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode reverseList(ListNode head) { if(head == null) { return head; } ListNode curr = head; ListNode prev = null; while (curr != null) { ListNode tmp = curr.next; curr.next = prev; prev = curr; curr = tmp; } return prev; } }
021 合并两个有序链表:循环迭代,声明 head = new ListNode(0); curr = head,循环curr,避免无法返回的问题,因为需要返回头指针,即 head.next
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode head = new ListNode(0); ListNode curr = head; while (l1 != null && l2 != null){ if (l1.val < l2.val) { curr.next = l1; l1 = l1.next; } else { curr.next = l2; l2 = l2.next; } curr = curr.next; } curr.next = l1 == null? l2 : l1; return head.next; } }
015 三数之和:先排序,双指针+循环,注意结果去重(3个地方),防止越界,Arrays.asList(^)
class Solution { public List<List<Integer>> threeSum(int[] nums) { int length = nums.length; Arrays.sort(nums); List<List<Integer>> ans = new ArrayList<List<Integer>>(); for (int i = 0; i < nums.length; i++) { if (nums[i] > 0) { continue; } if (i >= 1 && nums[i] == nums[ i- 1]) { continue; } int left = i +1; int right = length -1; while (left < right) { int sum = nums[i] + nums[left] + nums[right]; if (sum == 0) { ans.add(Arrays.asList(nums[i], nums[left],nums[right])); while (left < right && nums[left] == nums[left + 1]){ left++; } while (left < right && nums[right] == nums[right - 1]){ right--; } left++; right--; } else if (sum > 0) { right--; } else { left++; } } } return ans; } }
046 全排列:回溯法
public static List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
int[] visited = new int[nums.length];
backtrack(res, nums, new ArrayList<Integer>(), visited);
return res;
}
private static void backtrack(List<List<Integer>> res, int[] nums, ArrayList<Integer> tmp, int[] visited) {
//tmp 用来临时保存一次全排列的结果
if (tmp.size() == nums.length) {
res.add(new ArrayList<Integer>(tmp));
return;
}
for (int i = 0; i < nums.length; i++) {
if (visited[i] == 1) {
continue;
}
visited[i] = 1;
tmp.add(nums[i]);
backtrack(res, nums, tmp, visited);
//回溯结束之后,更新tmp,还原
visited[i] = 0;
tmp.remove(tmp.size() - 1);
}
}
384 打乱数组:
public int[] reset() { array = original; //记得再复制一份original original = original.clone(); return original; } public int[] shuffle() { // i只能与后面未交换的位置进行交换 for (int i = 0; i < array.length; i++) { swapAt(i, rand.nextInt(array.length - i) + i); } return array; }
053 最大子序列和:
public static int maxSubArray(int[] nums) { int sum = 0; int ans = nums[0]; for (int num : nums) { if (sum > 0) { sum += num; } else { sum = num; } ans = Math.max(sum, ans); } return ans; }
253 会议室II,VIP
289 生命游戏:特殊值,使用-1和2代表生命状态的转化;遍历的边界问题,使用数组{-1,0,1}来简化代码
class Solution { static int[] location = new int[]{-1,0,1}; public static void gameOfLife(int[][] board) { if (board == null ){ return ; } int row = board.length; int col = board[0].length; for (int i = 0; i < row;i++) { for (int j = 0; j < col; j++) { int sum = statistic(board, i, j, row, col); //统计活的个数 if (board[i][j] == 0 && sum == 3){ board[i][j] = 2; } else if (board[i][j] == 1 && sum < 2){ board[i][j] = -1; } else if (board[i][j] == 1 && sum > 3){ board[i][j] = -1; } } } for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (board[i][j] == 2){ board[i][j] = 1; }else if (board[i][j] == -1){ board[i][j] = 0; } } } } private static int statistic(int[][] board, int row, int col, int maxRow, int maxCol) { int total = 0; for (int i = 0; i< location.length; i++) { for (int j = 0; j < location.length; j++) { if (!(location[i] == 0 && location[j] == 0)) { // 相邻位置的坐标,注意是 location【i】而不是i int r = (row + location[i]); int c = (col + location[j]); // 查看相邻的细胞是否是活细胞 if ((r < maxRow && r >= 0) && (c < maxCol && c >= 0) ) { if((Math.abs(board[r][c]) == 1)){ total++; } } } } } return total; } }
128 最长连续序列:set+Math.max: 输入:[100,4,200,1,3,2],输出: 4,最长连续序列是[1,2,3,4]。它的长度为4。
class Solution { public static int longestConsecutive(int[] nums) { if(nums == null || nums.length == 0){ return 0; } Set<Integer> set = new HashSet<Integer>(); for(int i = 0; i< nums.length; i++) { set.add(nums[i]); } int ans = 0; for (int i = 0; i< nums.length; i++) { if (set.contains(nums[i] - 1)){ continue; } int tmp = nums[i]; int tmpLength = 0; while (set.contains(tmp)){ tmpLength += 1; tmp += 1; ans = Math.max(tmpLength, ans); } } return ans; } }
148 排序链表:归并排序+递归:
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode sortList(ListNode head) { if(head == null || head.next == null){ return head; } ListNode fast = head.next; ListNode slow = head; while(fast != null && fast.next != null){ fast = fast.next.next; slow = slow.next; } ListNode tmp = slow.next; slow.next = null; ListNode left = sortList(head); ListNode right = sortList(tmp); ListNode h = new ListNode(0); ListNode res = h; while(left!= null && right != null){ if (left.val < right.val){ h.next = left; left = left.next; }else { h.next = right; right = right.next; } h = h.next; } h.next = left == null? right : left; return res.next; } }
300 最长上升子序列:动态规划
class Solution { public static int lengthOfLIS(int[] nums) { if (nums== null || nums.length == 0){ return 0; } int[] dp = new int[nums.length]; dp[0] = 1; for (int i = 0; i < nums.length; i++){ int maxVal = 0; for (int j = 0;j < i; j++){ if (nums[j] < nums[i]){ maxVal = Math.max(maxVal, dp[j]); } } dp[i] = maxVal + 1; } int res = 0; for (int i = 0; i < nums.length; i++){ res = Math.max(res, dp[i]); } return res; } }
179 最大数:注意:Comparator,排序之后。0是asStrs的最大值,则返回0,避免多个0
思考:大数据全排列
class Solution { private class LargerNumberComparator implements Comparator<String> { @Override public int compare(String a, String b) { String order1 = a + b; String order2 = b + a; return order2.compareTo(order1); } } public String largestNumber(int[] nums) { String[] asStrs = new String[nums.length]; for (int i = 0; i < nums.length; i++) { asStrs[i] = String.valueOf(nums[i]); } Arrays.sort(asStrs, new LargerNumberComparator()); String largestNumberStr = new String(); for (String numAsStr : asStrs) { largestNumberStr += numAsStr; } return largestNumberStr; } }
022 括号生成:回溯法
200 岛屿数量:BFS,
class Solution { public int numIslands(char[][] grid) { if (grid == null || grid.length == 0){ return 0; } int ans = 0; int row = grid.length; int col = grid[0].length; for (int i = 0; i< row; i++) { for (int j = 0; j< col; j++){ if (grid[i][j] == '1'){ dfs(grid, i, j); ans++; } } } return ans; } private void dfs(char[][] grid, int i, int j) { int row = grid.length; int col = grid[0].length; if (i < 0 || j < 0 || i >= row || j >= col){ return; } if (grid[i][j] == '0'){ return; } grid[i][j]='0'; dfs(grid, i-1, j); dfs(grid, i , j-1); dfs(grid, i+1, j); dfs(grid, i, j+1); } }
287 寻找重复数:二分查找
class Solution { public int findDuplicate(int[] nums) { int n = nums.length; int l = 1, r = n - 1, ans = -1; while (l <= r) { int mid = (r-l) / 2 + l; int cnt = 0; for (int i = 0; i < n; ++i) { if (nums[i] <= mid) { cnt++; } } if (cnt <= mid) { l = mid + 1; } else { r = mid - 1; ans = mid; } } return ans; } }
054 螺旋矩阵
class Solution { public List<Integer> spiralOrder(int[][] matrix) { List<Integer> list = new ArrayList<Integer>(); if (matrix == null || matrix.length == 0) { return list; } int m = matrix.length; int n = matrix[0].length; int i = 0; //统计矩阵从外向内的层数,如果矩阵非空,那么它的层数至少为1层 int count = (Math.min(m, n) + 1) / 2; //从外部向内部遍历,逐层打印数据 while (i < count) { for (int j = i; j < n - i; j++) { list.add(matrix[i][j]); } for (int j = i + 1; j < m - i; j++) { list.add(matrix[j][(n - 1) - i]); } for (int j = (n - 1) - (i + 1); j >= i && (m - 1 - i != i); j--) { list.add(matrix[(m - 1) - i][j]); } for (int j = (m - 1) - (i + 1); j >= i + 1 && (n - 1 - i) != i; j--) { list.add(matrix[j][i]); } i++; } return list; } }