HOT100--Day23--153. 寻找旋转排序数组中的最小值,4. 寻找两个正序数组的中位数,20. 有效的括号

HOT100--Day23--153. 寻找旋转排序数组中的最小值,4. 寻找两个正序数组的中位数,20. 有效的括号

每日刷题系列。今天的题目是《力扣HOT100》题单。

题目类型:二分查找,栈。

关键:

今天的题目都是"多次二分"

153题,掌握"旋转排序数组"的特性和操作。

20题,可以用stack,可以用字符数组原地模拟栈,可以用switch case

153. 寻找旋转排序数组中的最小值

思路:

和最后一个元素比较。

二分查找[0,n-2]的内容,n-1不用管,是比较的对象。

如果x比最后一个数小,要么是最小值,要么x在最小值右侧。right = mid - 1;

如果x大于等于最后一个数。一定有两段,且目前x在第一段。left = mid + 1;

java 复制代码
class Solution {
    public int findMin(int[] nums) {
        int n = nums.length;
        int left = 0;
        int right = n - 2;

        // 二分查找[0,n-2]的内容,n-1不用管,是比较的对象
        while (left <= right) {
            int mid = left + ((right - left) >> 1);
            int x = nums[mid];

            // 如果x比最后一个数小,要么是最小值,要么x在最小值右侧
            if (x < nums[n - 1]) {
                right = mid - 1;
            } else {

                // 如果x大于等于最后一个数。一定有两段,且目前x在第一段。
                left = mid + 1;
            }
        }
        return nums[right + 1];
    }
}
  • 情况一:最小值在最左边,整个数组递增。会一直执行right = mid -1;left一直等于0。最后在right = -1的时候退出循环,这时候返回nums[right+1],就是nums[0],正确。
  • 情况二:最小值在最右边,其实也是分成了两端了。会一直执行left = mid +1;right一直等于n-2直到退出循环。这时候返回nums[right+1],就是nums[n-1],正确。
  • 其他情况:分成两段,全局最小值,在右段的第一个。最终会因为left>right退出循环,而退出循环时,right会在第一段的最后一个元素,也就是全局最大值的地方,返回nums[right+1],就是第二段的第一个元素,全局最小值。(这里也是退出循环时,left的位置)

4. 寻找两个正序数组的中位数

思路:

先不做,跳过,二刷再做。

java 复制代码
class Solution {
    public double findMedianSortedArrays(int[] a, int[] b) {
        if (a.length > b.length) {
            // 交换 a 和 b
            int[] tmp = a;
            a = b;
            b = tmp;
        }

        int m = a.length;
        int n = b.length;
        // 循环不变量:a[left] <= b[j+1]
        // 循环不变量:a[right] > b[j+1]
        int left = -1;
        int right = m;
        while (left + 1 < right) { // 开区间 (left, right) 不为空
            int i = (left + right) / 2;
            int j = (m + n + 1) / 2 - i - 2;
            if (a[i] <= b[j + 1]) {
                left = i; // 缩小二分区间为 (i, right)
            } else {
                right = i; // 缩小二分区间为 (left, i)
            }
        }

        // 此时 left 等于 right-1
        // a[left] <= b[j+1] 且 a[right] > b[j'+1] = b[j],所以答案是 i=left
        int i = left;
        int j = (m + n + 1) / 2 - i - 2;
        int ai = i >= 0 ? a[i] : Integer.MIN_VALUE;
        int bj = j >= 0 ? b[j] : Integer.MIN_VALUE;
        int ai1 = i + 1 < m ? a[i + 1] : Integer.MAX_VALUE;
        int bj1 = j + 1 < n ? b[j + 1] : Integer.MAX_VALUE;
        int max1 = Math.max(ai, bj);
        int min2 = Math.min(ai1, bj1);
        return (m + n) % 2 > 0 ? max1 : (max1 + min2) / 2.0;
    }
}

20. 有效的括号

思路:

把字符数组模拟成栈,空间复杂度O(1)。

注意,Java字符串转成字符数组时,会复制,所以空间复杂度是O(n)。可以用指针的语言的空间复杂度是O(1)

  1. 如果是左括号?进栈
  2. 如果是右括号?
    1. 首先栈内要有元素,检查跟栈顶元素是否匹配
      1. 匹配,出栈
      2. 不匹配,返回false
  3. 最后需要是空栈
java 复制代码
class Solution {
    // 思路:利用字符数组作栈
    public boolean isValid(String s) {
        char[] ch = s.toCharArray();
        int top = 0;
        for (int i = 0; i < ch.length; i++) {
            char c = ch[i];
            // 如果是左括号?进栈
            if (isLeft(c)) {
                ch[top++] = c;
            } else {
                // 如果是右括号?
                // 首先栈内要有元素,检查跟栈顶元素是否匹配
                if (top > 0 && isMatched(ch[top - 1], c)) {
                    // 匹配,出栈
                    top--;
                } else {
                    // 不匹配,返回false
                    return false;
                }
            }
        }
        // 最后需要是空栈
        return top == 0;
    }

    private boolean isLeft(char c) {
        if (c == '(' || c == '{' || c == '[') {
            return true;
        } else {
            return false;
        }
    }

    private boolean isMatched(char a, char b) {
        if (a == '(' && b == ')' || a == '[' && b == ']' || a == '{' && b == '}') {
            return true;
        } else {
            return false;
        }
    }
}

思路:

使用stack库函数。其实大同小异。

java 复制代码
class Solution {
    // 思路:利用字符数组作栈
    public boolean isValid(String s) {
        char[] ch = s.toCharArray();
        Deque<Character> stack = new ArrayDeque<>();
        for (int i = 0; i < ch.length; i++) {
            char c = ch[i];
            // 如果是左括号?进栈
            if (isLeft(c)) {
                stack.push(c);
            } else {
                // 如果是右括号?
                // 首先栈内要有元素,检查跟栈顶元素是否匹配
                if (!stack.isEmpty() && isMatched(stack.peek(), c)) {
                    // 匹配,出栈
                    stack.pop();
                } else {
                    // 不匹配,返回false
                    return false;
                }
            }
        }
        // 最后需要是空栈
        return stack.isEmpty();
    }

    private boolean isLeft(char c) {
        if (c == '(' || c == '{' || c == '[') {
            return true;
        } else {
            return false;
        }
    }

    private boolean isMatched(char a, char b) {
        if (a == '(' && b == ')' || a == '[' && b == ']' || a == '{' && b == '}') {
            return true;
        } else {
            return false;
        }
    }
}

思路:

使用switch case

java 复制代码
class Solution {
    public boolean isValid(String s) {
        char[] ss = s.toCharArray();
        Deque<Character> stack = new ArrayDeque<>();
        for (char c : ss) {
            switch(c){
                case '(':
                case '[':
                case '{': stack.push(c);break;
                case ')': if(stack.isEmpty()||stack.pop()!='(') return false;break;
                case ']': if(stack.isEmpty()||stack.pop()!='[') return false;break;
                case '}': if(stack.isEmpty()||stack.pop()!='{') return false;break;
            }
        }
        return stack.isEmpty();
    }
}
相关推荐
1白天的黑夜11 天前
栈-844.比较含退格的字符串-力扣(LeetCode)
c++·leetcode·
1白天的黑夜11 天前
栈-1047.删除字符串中的所有相邻重复项-力扣(LeetCode)
c++·leetcode·
hope_wisdom3 天前
C/C++数据结构之栈基础
c语言·数据结构·c++··stack
一叶难遮天3 天前
Android面试指南(八)
java·设计模式·数组·hashmap·string·android面试·匿名内部类
今后1234 天前
【数据结构】栈详解
数据结构·
KarrySmile7 天前
Day12--HOT100--23. 合并 K 个升序链表,146. LRU 缓存,94. 二叉树的中序遍历
数据结构·链表·二叉树·递归·hot100·lru·灵茶山艾府
南莺莺8 天前
假设一个算术表达式中包含圆括号、方括号和花括号3种类型的括号,编写一个算法来判别,表达式中的括号是否配对,以字符“\0“作为算术表达式的结束符
c语言·数据结构·算法·
Q741_1479 天前
C++ 面试高频考点 力扣 153. 寻找旋转排序数组中的最小值 二分查找 题解 每日一题
c++·算法·leetcode·面试·二分查找
玩镜的码农小师兄9 天前
[从零开始面试算法] (11/100) LeetCode 226. 反转二叉树:递归的“镜像”魔法
c++·算法·leetcode·面试·递归·hot100