day06-算法热题10题

LeetCode 热题 Hot 100

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
  public ListNode detectCycle(ListNode head) {
        if (head == null) return null;
        ListNode fast = head, slow = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (fast == slow) {
                break;
            }
        }
        // 上面的代码类似 hasCycle 函数
        if (fast == null || fast.next == null) {
            // fast 遇到空指针说明没有环
            return null;
        }
        // 将快指针置回头部,慢指针每次走一步,快指针也每次走一步,直到相遇
        fast = head;
        // 快慢指针同步前进,相交点就是环起点
        while (fast != slow) {
            fast = fast.next;
            slow = slow.next;
        }
        return fast;
    }
}
 class LRUCache {
        LinkedHashMap<Integer, Integer> cache;
        int capacity;

        public LRUCache(int capacity) {
           // 按照访问顺序存放
            cache = new LinkedHashMap<>(capacity + 1, 0.75f, true);
            this.capacity = capacity;
        }

        public int get(int key) {
            if (!cache.containsKey(key)) {
                return -1;
            }
            return cache.get(key);
        }

        public void put(int key, int value) {
            // 修改 key 的值
            cache.put(key, value);
            if (cache.size() > capacity) {
                // 链表头部就是最久未使用的 key
                int oldestKey = cache.keySet().iterator().next();
                cache.remove(oldestKey);
            }
        }
    }
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
 /**
     * 归并排序:
     * 先分解到最小单元,然后逐个进行合并并排序,这样在合并的时候,
     * 其实两个链表本身就是有序的,那么当有一个全部取完后,另一个可以直接拼接在最后面
     */
    public ListNode sortList(ListNode head) {
        // 链表为空或者只有一个节点的时候
        if (head == null || head.next == null) return head;
        // 查找出后半部分的链表
        ListNode lastNode = getLastNode(head);
        // 递归操作
        ListNode l1 = sortList(head);
        ListNode l2 = sortList(lastNode);
        // 合并
        return merge(l1, l2);
    }

    private ListNode merge(ListNode l1, ListNode l2) {
        if (l1 == null) return l2;
        if (l2 == null) return l1;
        if (l1.val < l2.val) {
            l1.next = merge(l1.next, l2);
            return l1;
        } else {
            l2.next = merge(l2.next, l1);;
            return l2;
        }
    }

    private ListNode getLastNode(ListNode node) {
        if (node == null) return null;
        // 快慢指针寻找到中间节点
        ListNode fast = node, slow = node;
        // 划分节点
        ListNode breakNode = node;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            breakNode = slow;
            slow = slow.next;
        }
        breakNode.next = null;
        return slow;
    }
}

class Solution {
  /**
     * 2,3,-2,4
     * 如果是正整数可以如下做法
     * dp[0] = 2
     * dp[1] = Math.max(3, 3 * dp[0]) = 6
     * dp[i] = Math( nums[i], nums[i] * dp[i-1] )  其中 i >=1
     * <p>
     * <p>
     * 但是这里不能这么做,需要两个dp
     */
    public int maxProduct(int[] nums) {
     int n = nums.length;
        // 乘积最大子数组的乘积值
        int[] dpMax = new int[n];
        // 乘积最小子数组的乘积值
        int[] dpMin = new int[n];
        dpMax[0] = nums[0];
        dpMin[0] = nums[0];
        int max = nums[0];
        for (int i = 1; i < n; i++) {
            // 当前位置的值    max( 最小的dpMin的前一个位置 * 当前位置的值 和 dpMax的前一个位置 * 当前位置的值 )
            dpMax[i] = Math.max(nums[i], Math.max(dpMin[i - 1] * nums[i], dpMax[i - 1] * nums[i]));
            dpMin[i] = Math.min(nums[i], Math.min(dpMax[i - 1] * nums[i], dpMin[i - 1] * nums[i]));
            if (max < dpMax[i]) {
                max = dpMax[i];
            }
        }
        return max;
    }
}
  class MinStack {
        Stack<Integer> stack;
        Stack<Integer> minStack;

        public MinStack() {
            stack = new Stack<>();
            minStack = new Stack<>();
        }

        public void push(int val) {
            stack.push(val);
            if (minStack.isEmpty() || minStack.peek() >= val) {
                minStack.push(val);
              } else {
                minStack.push(Math.min(val, minStack.peek()));
            }
        }

        public void pop() {
            if (minStack.isEmpty()) {
                return;
            }
            minStack.pop();
            stack.pop();
        }

        public int top() {
            return stack.peek();
        }

        public int getMin() {
            return minStack.peek();
        }
    }

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
 public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode A = headA, B = headB;
        while (A != B) {
            A = A == null ? headB : A.next;
            B = B == null ? headA : B.next;
        }
        return A;
    }
}
class Solution {
/**
     * 摩尔投票:
     * 选出投票数最多的
     */
    public int majorityElement(int[] nums) {
        int candidate = 0, count = 0, n = nums.length;
        for (int num : nums) {
            if (count == 0) {
                candidate = num;
                count = 1;
            } else {
                count += (num == candidate) ? 1 : -1;
            }
        }
        return candidate;
    }
}
class Solution {
   /**
     * 动态规划
     */
    public int rob(int[] nums) {
        int n = nums.length;
        if (n == 1) return nums[0];
        // dp[][0] 没有偷第i个
        // dp[][1] 偷了第i个
        int[][] dp = new int[n][2];
        // dp[i][0] 从 0~i不偷第i个房屋获得的最高金额
        // dp[i][1] 偷第i个房屋获得的最高金额
        dp[0][0] = 0;
        dp[0][1] = nums[0];
        for (int i = 1; i < n; i++) {
            dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1]);
            dp[i][1] = dp[i - 1][0] + nums[i];
        }
        return Math.max(dp[n - 1][0], dp[n - 1][1]);
    }
}
class Solution {
   /**
     * DFS
     * 将周围的1变成0,直到找不到为之 然后位置移动到下一次找到1为止然后重复进行
     */
    public int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0) return 0;
        int res = 0;
        int row = grid.length;
        int col = grid[0].length;
        // 遍历 grid
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                // 每发现一个岛屿,岛屿数量加一
                if (grid[i][j] == '1') {
                    res += 1;
                    // 然后使用 DFS 将岛屿淹了
                    dfs(grid, i, j, row, col);
                }
            }
        }
        return res;
    }

      // 从 (i, j) 开始,将与之相邻的陆地都变成海水
    private void dfs(char[][] grid, int x, int y, int row, int col) {
        if (x < 0 || y < 0 || x >= row || y >= col || grid[x][y] == '0') {
            return;
        }
        grid[x][y] = '0';
        // 淹没上下左右的陆地
        dfs(grid, x + 1, y, row, col);
        dfs(grid, x - 1, y, row, col);
        dfs(grid, x, y - 1, row, col);
        dfs(grid, x, y + 1, row, col);
    }
}
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
      public ListNode reverseList(ListNode head) {
        return reverse(null, head);
    }

    private ListNode reverse(ListNode pre, ListNode cur) {
        if (cur == null) return pre;
        ListNode next = cur.next;
        cur.next = pre;
        return reverse(cur, next);
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫吹过的柚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值