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 括号生成:回溯法

class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> res = new ArrayList<>();
        dfs(res, n, n, "");
        return res;
    }

    private void dfs(List<String> res, int left, int right, String curStr) {
        if (left == 0 && right == 0) { // 左右括号都不剩余了,说明找到了有效的括号
            res.add(curStr);
            return;
        }
        //左括号只有剩余的时候才可以选,如果左括号的数量已经选完了,是不能再选左括号了。
        //如果选完了左括号我们是还可以选择右括号的。
        if (left < 0)
            return;
        // 如果右括号剩余数量小于左括号剩余的数量,说明之前选择的无效
        if (right < left)
            return;
            //选择左括号
            dfs(res, left - 1, right, curStr + "(");
            //选择右括号
            dfs(res, left, right - 1, curStr + ")");
    }
}

 

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

 

posted @ 2020-08-24 16:30  傑0327  阅读(158)  评论(0编辑  收藏  举报