day02-算法热题10题

LeetCode 热题 Hot 100

class Solution {
     public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        // 遍历每个字符,看是否括号匹配
        for (char c : s.toCharArray()) {
            if (c == '(' || c == '{' || c == '[') {
                stack.push(c);
            } else {
                // 如果栈为空,代表没有右括号
                if (stack.isEmpty()) {
                    return false;
                }
                // 有括号的话,就要pop出来和顶部的对比
                Character top = stack.pop();
                if (!mathch(c, top)) {
                    return false;
                }
            }
        }
        return stack.isEmpty();
    }

    /**
     * 判断是否匹配
     */
    public boolean mathch(char c, char top) {
        return (c == ')' && top == '(') || (c == '}' && top == '{') || (c == ']' && top == '[');
    }
}

    class Solution {
    /**
     * 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; }
     * }
     */
    /**
     * 方法1: 递归方式
     */
    public ListNode mergeTwoLists1(ListNode list1, ListNode list2) {
      if (list1 == null) return list2;
        if (list2 == null) return list1;
        if (list1 == null && list2 == null) return null;
        ListNode res = list1.val <= list2.val ? list1 : list2;
        res.next = mergeTwoLists(res.next,list1.val > list2.val? list1 : list2);
        return res;
    }
    /**
     * 方法2: 迭代方式
     */
    public ListNode mergeTwoLists2(ListNode list1, ListNode list2) {
        // 处理两个都为null的情况
        if (list1 == null && list2 == null) return null;
        // 处理两个其中一个为null的情况
        if (list1 == null) return list2;
        if (list2 == null) return list1;
        // 用来保存最终结果
        ListNode dummy = new ListNode(0);
        // head用来遍历使用
        ListNode head = dummy;
        // 当两个链表遍历都不为空时
        while (list1 != null && list2 != null) {
            if (list1.val <= list2.val) {
                head.next = list1;
                list1 = list1.next;
            } else {
                head.next = list2;
                list2 = list2.next;
            }
            head = head.next;
        }
        // 如果遍历完list1不为空
        while (list1 != null) {
            head.next = list1;
            list1 = list1.next;
            head = head.next;
        }
        // 如果遍历完list2不为空
        while (list2 != null) {
            head.next = list2;
            list2 = list2.next;
            head = head.next;
        }
        return dummy.next;
    }
}
class Solution {
    /**
     * 设置全局列表存储最后的结果
     */
    private List<String> pathList = new LinkedList<>();

    /**
     * 括号对数
     */
    private int maxPairCount = 0;

    /**
     * 深度优先遍历
     */
    public List<String> generateParenthesis(int n) {
        maxPairCount = n;
        dfs("", 0, 0);
        return pathList;
    }


    private void dfs(String path, int leftCount, int rightCount) {
        // 判断有没有走到终点
        if (path.length() == (maxPairCount << 1)) {
            pathList.add(path);
            return;
        }
           // 判断dfs有没有走到终点
        if (path.length() == (maxPairCount << 1)) {
            pathList.add(path);
            return;
        }
        // 如果左括号个数还没用完
        if (leftCount < maxPairCount) {
            dfs(path + "(", leftCount + 1, rightCount);
        }
        // 如果右括号个数小于左括号个数
        if (rightCount < leftCount) {
            dfs(path + ")", leftCount, rightCount + 1);
        }
    }
}
/**
 * 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 mergeKLists(ListNode[] lists) {
        // 判断链表是否为null
        if (lists.length == 0) return null;
        // 用优先级队列最小堆来处理,升序处理: (x, y) -> x.val - y.val
        Queue<ListNode> queue = new PriorityQueue<>(Comparator.comparingInt(x -> x.val));
        // 把node全部添加到最小堆里去了,
        for (ListNode head : lists) {
            while (head != null) {
                // 添加
                queue.offer(head);
                head = head.next;
            }
        }
        ListNode dummy = new ListNode(0);
        ListNode head = dummy;
        // 队列不为空,就出队
        while (!queue.isEmpty()) {
            // 把最小的元素拿到了
            // 移除
            // 第一个有效的元素
            head.next = queue.poll();
            head = head.next;
            if (queue.isEmpty()) {
                head.next = null;
            }
        }
        return dummy.next;
    }
}
class Solution {
       /**
     * 深度优先遍历找规律
     * 1 4 3 2 0
     * ---------
     * i     j
     */
    public void nextPermutation(int[] nums) {
        int n = nums.length;
        if (n == 1) return;
        // 下标要保证有效 n>=2
        int i = n - 2;
        // 从右往左看,找到那个开始递减的位置,看14320也就是 i=
        while (i >= 0 && nums[i] >= nums[i + 1]) {
            i--;
        }
        // 如果i<0代表这个序列是全部递减的,所以我们只需要将数组逆序排序处理就行
        if (i < 0) {
            reverse(nums, 0, n - 1);
        } else {
            // 我们从末尾的下标去定位到那个第一个开始递减的位置
            int j = n - 1;
            while (i < j && nums[j] <= nums[i]) {
                j--;
            }
            // 找到了就可以开始交换
            swap(nums, i, j);
            reverse(nums, i + 1, n - 1);
        }
    }

    private void reverse(int[] nums, int start, int end) {
        while (start <= end) {
            swap(nums, start, end);
            start++;
            end--;
        }
    }

    /**
     * 交换两个数字
     */
    private void swap(int[] nums, int i, int j) {
        if (i == j) return;
        nums[i] = nums[i] ^ nums[j];
        nums[j] = nums[i] ^ nums[j];
        nums[i] = nums[i] ^ nums[j];
    }
暂时不写

class Solution {

    /**
     * 方法1: 暴力
     */
    public int search1(int[] nums, int target) {
        for (int i = 0; i < nums.length; i++) {
            if (target == nums[i]) return i;
        }
        return -1;
    }
     
     /**
     * 方法2: 二分查找
     * 因为有序分为2段,进行二分查找
     */
    public int search2(int[] nums, int target) {
        int n = nums.length;
        if (n == 0) return -1;
        //
        if (n == 1) return nums[0] == target ? 0 : -1;
        // 记录翻转的位置
        int cutoff = -1;
        for (int i = 0; i < n - 1; i++) {
            // 此时代表是旋转的位置
            if (nums[i] > nums[i + 1]) {
                cutoff = i;
                break;
            }
        }
        // 左边进行二分查找
        int left = binarySearch(nums, 0, cutoff, target);
        // 右边进行二分查找
        int right = binarySearch(nums, cutoff + 1, n - 1, target);
        // 看看左边的有没有找到,找不到就是右边
        return left == -1 ? right : left;
    }

    private int binarySearch(int[] nums, int start, int end, int target) {
        // 升序的数组
        while (start <= end) {
            int mid = start + ((end - start) >>> 1);
            if (nums[mid] == target) return mid;
            else if (nums[mid] < target) start = mid + 1;
            else{
                end = mid - 1;
            }
        }
        return -1;
    }
}

   /**
     * 二分查找
     */
    public int[] searchRange1(int[] nums, int target) {
        int n = nums.length;
        // 从0到n-1找到第一个出现target的下标
        int first = findFirst(nums, target, 0, n - 1);
        // 从找到的第一个下标开始往后找第二个下标,这里有可能我返回的是-1,所以是下标0的时候
        int last = findLast(nums, target, Math.max(first, 0), n - 1);
        return new int[]{first, last};
    }

    private int findFirst(int[] nums, int target, int start, int end) {
        while (start <= end) {
            int mid = start + ((end - start) >>> 1);
            // 因为有重复元素,所以这里我们不能直接去返回
            if (nums[mid] == target) {
                // 判断前面的那个是否等于这个mid对应的值如果就mid-1,这里得考虑mid -1 >= 0的情况
                if (mid >= 1 && nums[mid - 1] == nums[mid]) {
                    end = mid - 1;
                } else {
                    return mid;
                }
            } else if (nums[mid] > target) {
                end = mid - 1;
            } else {
                start = mid + 1;
            }
        }
        return -1;
    }

    private int findLast(int[] nums, int target, int start, int end) {
        while (start <= end) {
            int mid = start + ((end - start) >>> 1);
            // 因为有重复元素,所以这里我们不能直接去返回
            if (nums[mid] == target) {
                // 判断前面的那个是否等于这个mid对应的值如果就mid+1,这里得考虑mid +1 <= enc的情况
                if (mid <= end - 1 && nums[mid] == nums[mid + 1]) {
                    start = mid + 1;
                } else {
                    return mid;
                }
            } else if (nums[mid] > target) {
                end = mid - 1;
            } else {
                start = mid + 1;
            }
        }
        return -1;
    }

class Solution {
   /**
     * 最终结果
     */
    private List<List<Integer>> pathList = new ArrayList<>();
    /**
     * 记录路径
     */
    List<Integer> path = new ArrayList<>();

    int sum = 0;

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        int n = candidates.length;
        dfs(candidates, target, 0, n);
        return pathList;
    }

    /**
     * target 目标值
     * start 遍历到哪个位置了
     */
    public void dfs(int[] candidates, int target, int start, int end) {
        // 当sum>target的是终止条件
        if (sum > target) {
            return;
        }
        // 当sum=target的时候进行收集元素
        if (sum == target) {
            pathList.add(new ArrayList<>(path));
            return;
        }
         while (start < end) {
            path.add(candidates[start]);
            sum += candidates[start];
            // 为什么从start开始,而不是start+1因为还可以可以继续取用之前的值
            dfs(candidates, target, start, end);
            // 移除最后一个值
            sum -= candidates[start];
            // 去除path的最后一个元素
            path.remove(path.size() - 1);
            start++;
        }
    }
}
class Solution {
  /**
     * 分左右两部分以最大高度为分界点
     * i处接雨水的高度取决于i-1和i+1两侧的最小高度决定
     * 分别从两边往最高点遍历,如果下一个数比当前数小,说明可以接到水
     */
    public int trap(int[] height) {
        int res = 0;
        int maxHeightIndex = 0;
        int maxHeight = 0;
        // 找到最大的高度以及对应的下标
        for (int i = 0; i < height.length; i++) {
            if (height[i] >= maxHeight) {
                maxHeight = height[i];
                maxHeightIndex = i;
            }
        }
        // 处理左边部分
        for (int i = 0; i < maxHeightIndex; i++) {
            for (int j = i + 1; j <= maxHeightIndex; j++) {
                // 左边的大于右边的才能接水
                if (height[i] > height[j]) {
                    // 左边的-右边的
                    res += height[i] - height[j];
                } else {
                    i = j;
                }
            }
        }

        // 处理右边部分
        for (int i = height.length - 1; i > maxHeightIndex; i--) {
            for (int j = i - 1; j >= maxHeightIndex; j--) {
                // 左边的小于右边的才能接水
                if (height[i] > height[j]) {
                    // 右边-左边的
                    res += height[i] - height[j];
                } else {
                    i = j;
                }
            }
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

枫吹过的柚

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

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

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

打赏作者

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

抵扣说明:

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

余额充值