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;
}
}

浙公网安备 33010602011771号