Android学习总结之算法篇六(数组和栈)

括号匹配

public static 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()) {
                    // 如果栈为空,说明没有匹配的左括号,返回 false
                    return false;
                }
                // 弹出栈顶元素
                char top = stack.pop();
                if ((c == ')' && top != '(') || (c == ']' && top != '[') || (c == '}' && top != '{')) {
                    // 如果右括号与栈顶的左括号不匹配,返回 false
                    return false;
                }
            }
        }
        // 如果栈为空,说明所有括号都匹配,返回 true
        return stack.isEmpty();
    }

子数组最大和

/**
     * 计算子数组的最大和
     * @param nums 整数数组
     * @return 子数组的最大和
     */
    public static int maxSubArray(int[] nums) {
        // 当前子数组的最大和
        int currentMax = nums[0];
        // 全局子数组的最大和
        int globalMax = nums[0];
        // 从数组的第二个元素开始遍历
        for (int i = 1; i < nums.length; i++) {
            // 更新当前子数组的最大和
            currentMax = Math.max(nums[i], currentMax + nums[i]);
            // 更新全局子数组的最大和
            globalMax = Math.max(globalMax, currentMax);
        }
        return globalMax;
    }

循环升序数组最小值

public class FindMinInRotatedSortedArray {
    // 此方法用于在循环升序数组中查找最小值
    public static int findMin(int[] nums) {
        // 初始化左指针,指向数组起始位置
        int left = 0;
        // 初始化右指针,指向数组末尾位置
        int right = nums.length - 1;

        // 当左指针小于右指针时,继续循环查找
        while (left < right) {
            // 计算中间位置,使用 left + (right - left) / 2 避免整数溢出
            int mid = left + (right - left) / 2;
            // 如果中间元素大于右边界元素,说明最小值在 mid 右侧
            if (nums[mid] > nums[right]) {
                // 更新左指针到 mid + 1 位置
                left = mid + 1;
            } else {
                // 否则,最小值在 mid 或 mid 左侧,更新右指针到 mid 位置
                right = mid;
            }
        }
        // 当 left 和 right 相遇时,该位置的元素即为最小值
        return nums[left];
    }

    public static void main(String[] args) {
        // 定义一个示例循环升序数组
        int[] nums = {3, 4, 5, 1, 2};
        // 调用 findMin 方法查找最小值并打印结果
        System.out.println("数组中的最小值是: " + findMin(nums));
    }
}    

字符串解码

class Solution {
    // 该方法用于对输入的编码字符串进行解码
    public String decodeString(String s) {
        // 用于存储重复次数的栈
        Stack<Integer> countStack = new Stack<>();
        // 用于存储待拼接的字符串的栈
        Stack<String> stringStack = new Stack<>();
        // 用于构建当前正在处理的字符串
        StringBuilder currentString = new StringBuilder();
        // 用于记录当前的重复次数
        int k = 0;
        // 遍历输入字符串中的每一个字符
        for (char c : s.toCharArray()) {
            // 如果当前字符是数字
            if (Character.isDigit(c)) {
                // 更新重复次数 k,考虑到多位数的情况
                k = k * 10 + (c - '0');
            // 如果当前字符是左括号 [
            } else if (c == '[') {
                // 将当前的重复次数 k 压入 countStack 栈中
                countStack.push(k);
                // 将当前已经构建好的字符串压入 stringStack 栈中
                stringStack.push(currentString.toString());
                // 清空 currentString,准备处理括号内的字符串
                currentString = new StringBuilder();
                // 重置重复次数 k 为 0
                k = 0;
            // 如果当前字符是右括号 ]
            } else if (c == ']') {
                // 从 stringStack 栈中弹出上一个字符串
                StringBuilder decodeString = new StringBuilder(stringStack.pop());
                // 从 countStack 栈中弹出重复次数
                int count = countStack.pop();
                // 根据重复次数,将当前括号内的字符串添加到 decodeString 后面
                for (int i = 0; i < count; i++) {
                    decodeString.append(currentString);
                }
                // 更新 currentString 为 decodeString
                currentString = decodeString;
            // 如果当前字符是普通字符
            } else {
                // 将该字符添加到 currentString 后面
                currentString.append(c);
            }
        }
        // 返回最终解码后的字符串
        return currentString.toString();
    }
}

合并区间

class Solution {
     public static int[][] merge(int[][] intervals) {
        // 如果输入数组为空或者长度为 0,直接返回空数组
        if (intervals == null || intervals.length == 0) {
            return new int[0][0];
        }
        // 按照区间的起始位置进行排序
        Arrays.sort(intervals, Comparator.comparingInt(a -> a[0]));

        // 用于存储合并后的区间
        List<int[]> merged = new ArrayList<>();
        // 取第一个区间作为初始的合并区间
        int[] current = intervals[0];
        // 遍历剩余的区间
        for (int i = 1; i < intervals.length; i++) {
            int[] interval = intervals[i];
            // 如果当前区间的结束位置大于等于下一个区间的起始位置,说明有重叠
            if (current[1] >= interval[0]) {
                // 更新当前区间的结束位置为两个区间结束位置的最大值
                current[1] = Math.max(current[1], interval[1]);
            } else {
                // 没有重叠,将当前区间加入到合并列表中
                merged.add(current);
                // 更新当前区间为下一个区间
                current = interval;
            }
        }
        // 将最后一个合并的区间加入到列表中
        merged.add(current);

        // 将列表转换为二维数组并返回
        return merged.toArray(new int[merged.size()][]);
    }
}

合并两个有序数组

假设有两个有序数组 nums1 和 nums2,要将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。nums1 的长度足以容纳 nums2 的元素。

class Solution {
    // 该方法用于将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        // p1 指向 nums1 中有效元素的最后一个位置
        int p1 = m - 1;
        // p2 指向 nums2 中最后一个元素的位置
        int p2 = n - 1;
        // p 指向合并后数组的最后一个位置
        int p = m + n - 1;

        // 当 p1 和 p2 都未越界时,进行比较和赋值操作
        while (p1 >= 0 && p2 >= 0) {
            // 如果 nums1[p1] 大于 nums2[p2]
            if (nums1[p1] > nums2[p2]) {
                // 将 nums1[p1] 放到合并后数组的 p 位置
                nums1[p] = nums1[p1];
                // p1 指针左移一位
                p1--;
            } else {
                // 否则将 nums2[p2] 放到合并后数组的 p 位置
                nums1[p] = nums2[p2];
                // p2 指针左移一位
                p2--;
            }
            // p 指针左移一位
            p--;
        }

        // 如果 nums2 中还有剩余元素,将其依次放入 nums1 中
        while (p2 >= 0) {
            nums1[p] = nums2[p2];
            p2--;
            p--;
        }
    }
}    

合并K个有序数组

import java.util.PriorityQueue;

class Solution {
    // 该方法用于合并多个有序数组
    public int[] mergeKArrays(int[][] arrays) {
        // 如果输入的数组为空或者长度为 0,直接返回一个空数组
        if (arrays == null || arrays.length == 0) {
            return new int[0];
        }
        // 创建一个最小堆,用于存储每个数组的当前最小值
        PriorityQueue<Node> minHeap = new PriorityQueue<>((a, b) -> a.val - b.val);
        // 计算所有数组的总长度
        int totalLength = 0;

        // 遍历每个数组
        for (int i = 0; i < arrays.length; i++) {
            // 如果当前数组不为空
            if (arrays[i].length > 0) {
                // 将当前数组的第一个元素及其所在数组的索引和位置信息封装成 Node 放入最小堆中
                minHeap.offer(new Node(arrays[i][0], i, 0));
                // 累加当前数组的长度到总长度中
                totalLength += arrays[i].length;
            }
        }

        // 创建一个用于存储合并后结果的数组
        int[] result = new int[totalLength];
        // 结果数组的索引
        int index = 0;

        // 当最小堆不为空时,继续合并操作
        while (!minHeap.isEmpty()) {
            // 从最小堆中取出当前最小值对应的 Node
            Node node = minHeap.poll();
            // 将该最小值放入结果数组中
            result[index++] = node.val;
            // 如果该元素所在数组还有剩余元素
            if (node.col + 1 < arrays[node.row].length) {
                // 将该数组的下一个元素及其位置信息封装成 Node 放入最小堆中
                minHeap.offer(new Node(arrays[node.row][node.col + 1], node.row, node.col + 1));
            }
        }

        // 返回合并后的结果数组
        return result;
    }

    // 自定义 Node 类,用于存储元素的值、所在数组的索引和元素在数组中的位置
    static class Node {
        int val;
        int row;
        int col;

        // 构造函数,用于初始化 Node 对象
        Node(int val, int row, int col) {
            this.val = val;
            this.row = row;
            this.col = col;
        }
    }
}    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值