算法训练-数据结构

1.数组+移位/排序
1.数组元素循环左移p位后的结果。

循环左移和以下操作等价:

1.通过中间元素对称翻转

2.将数组分为n-p个和p个两部分

3.分别翻转这两个数组即可

c 复制代码
// 中心翻转
void Reverse(int R[], int left, int right) {
    while (left < right) {
        int temp = R[left];
        R[left] = R[right];
        R[right] = temp;
        left++;
        right--;
    }
}
//分组再翻转
void CyclicLeftShift(int R[], int n, int p) {
    Reverse(R, 0, n-1);       // 全部逆置
    Reverse(R, 0, p-1);       // 前p个逆置
    Reverse(R, p, n-1);       // 后n-p个逆置
}

2 .两个整数递增有序序列A,B分别有n和m个元素,求第K大的数(1≤k≤n+m),要求算法有最佳时间复杂度

例子:输入A={1,3,4,5,6},B={3,4,5,6},K=4

思路:

A、B递增,从大到小数到第k个即可。(时间复杂度o(k))

java 复制代码
public class KthLargestInTwoArrays {
    
    /**
     * 方法1:双指针合并 - 时间复杂度O(K),空间复杂度O(1)
     */
    public static int findKthLargest1(int[] A, int[] B, int k) {
        int n = A.length, m = B.length;
        int i = n - 1, j = m - 1; // 从后往前遍历(因为要求第K大)
        int count = 0;
        int result = 0;
        // 两个数组都还没数完的情况
        while (i >= 0 && j >= 0) {
            count++;
            if (A[i] >= B[j]) {
                if (count == k) return A[i];
                i--;
            } else {
                if (count == k) return B[j];
                j--;
            }
        }
        
        // 如果其中一个数组遍历完
        while (i >= 0) {
            count++;
            if (count == k) return A[i];
            i--;
        }
        
        while (j >= 0) {
            count++;
            if (count == k) return B[j];
            j--;
        }
    
        return -1; // k超出范围
    }
}

数学
3. 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0
思路:

相当于一个求一个减法运算,得到最大差值。

所以找到最大的被减数和最小的减数即可。

java 复制代码
public class StockProfit {
    public int maxProfit(int[] prices) {
        if (prices == null || prices.length == 0) {
            return 0;
        }
        //初始值-最低价格,遇到最低价格则更新
        int minPrice = Integer.MAX_VALUE;
        int maxProfit = 0;
        
        for (int i = 0; i < prices.length; i++) {
            // 更新最低价格
            if (prices[i] < minPrice) {
                minPrice = prices[i];
            }else if (prices[i] - minPrice > maxProfit) {
            // 计算当前价格卖出能获得的利润,更新最大利润
                maxProfit = prices[i] - minPrice;
            }
        }
        return maxProfit;
    }
}

数组+双指针

**4.**给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。

思路:

  • 相当于求出宽*高,也就是(b-a)*min(b,a)的最大值。乘数越大越好
  • 只需更换a,b的值就好,更换条件,比min(b,a)大则更换,否则不换
java 复制代码
	public class Solution {
    public int maxArea(int[] height) {
        int left = 0;                    // 左指针
        int right = height.length - 1;   // 右指针
        int maxArea = 0;                 // 最大面积
        
        while (left < right) {
            // 计算当前容器的面积
            int currentWidth = right - left;
            int currentHeight = Math.min(height[left], height[right]);
            int currentArea = currentWidth * currentHeight;
            
            // 更新最大面积
            maxArea = Math.max(maxArea, currentArea);
            
            // 移动较短的指针,希望找到更高的垂线
            if (height[left] < height[right]) {
                left++;
            } else {
                right--;
            }
        }
        
        return maxArea;
    }
}

列表 + 堆 遍历

**5.**有 k 个 非递减排列 的整数列表。找到一个最小 区间,使得 k 个列表中的每个列表至少有一个数包含在其中。
思路:

1.先随机取每个子列表的一个元素,存放在最小堆中,找出最大值和最小值组成区间

2.取出最小值,依次存入子列表的一个新值,更新最小区间

java 复制代码
public int[] smallestRange(List<List<Integer>> nums) {
        // 最小堆,存储三元组[元素值, 列表索引, 元素在列表中的索引]
        // 堆按照元素值进行排序,最小的元素在堆顶
        PriorityQueue<int[]> minHeap = new PriorityQueue<>((a, b) -> a[0] - b[0]);

        int currentMax = Integer.MIN_VALUE; // 记录当前堆中所有元素的最大值
        int k = nums.size(); // 列表的数量

        // 初始化堆:将每个列表的第一个元素加入堆中
        for (int i = 0; i < k; i++) {
            // 检查当前列表是否为空
            if (!nums.get(i).isEmpty()) {
                int val = nums.get(i).get(0); // 获取当前列表的第一个元素
                // 将三元组[元素值, 列表索引, 元素索引]加入堆
                minHeap.offer(new int[]{val, i, 0});
                // 更新当前最大值
                currentMax = Math.max(currentMax, val);
            }
        }

        // 初始化最小区间的起点和终点,设置为一个非常大的范围
        int start = -1000000, end = 1000000;
        int minRange = end - start; // 初始化最小区间长度

        // 当堆中有k个元素时继续处理(确保每个列表至少有一个元素在考虑范围内)
        while (minHeap.size() == k) {
            // 从堆中取出当前最小的元素
            int[] current = minHeap.poll();
            int currentVal = current[0];   // 最小元素的值
            int listIdx = current[1];      // 当前元素所在的列表索引
            int elementIdx = current[2];   // 当前元素在列表中的索引

            // 检查当前区间[currentVal, currentMax]是否比之前记录的最小区间更小
            // 或者区间长度相同但起点更小(题目要求返回最小的区间)
            if (currentMax - currentVal < minRange ||
                    (currentMax - currentVal == minRange && currentVal < start)) {
                // 更新最小区间信息
                minRange = currentMax - currentVal;
                start = currentVal;
                end = currentMax;
            }

            // 如果当前元素所在的列表还有下一个元素
            if (elementIdx + 1 < nums.get(listIdx).size()) {
                // 获取下一个元素的值
                int nextVal = nums.get(listIdx).get(elementIdx + 1);
                // 将下一个元素加入堆中
                minHeap.offer(new int[]{nextVal, listIdx, elementIdx + 1});
                // 更新当前最大值(因为新加入的元素可能比当前最大值更大)
                currentMax = Math.max(currentMax, nextVal);
            } else {
                // 如果当前列表已经遍历完,则退出循环
                // 因为无法保证每个列表至少有一个元素在区间内了
                break;
            }
        }

        // 返回找到的最小区间
        return new int[]{start, end};
    }
main(){
	Solution solution = new Solution();
        // 创建测试数据
        List<List<Integer>> nums = new ArrayList<>();
        nums.add(Arrays.asList(4, 10, 15, 24, 26));
        nums.add(Arrays.asList(0, 9, 12, 20));
        nums.add(Arrays.asList(5, 18, 22, 30));

        // 调用方法并输出结果
        int[] result = solution.smallestRange(nums);
}
相关推荐
胡萝卜3.02 小时前
掌握C++ map:高效键值对操作指南
开发语言·数据结构·c++·人工智能·map
松岛雾奈.2303 小时前
机器学习--PCA降维算法
人工智能·算法·机器学习
电子_咸鱼3 小时前
【STL string 全解析:接口详解、测试实战与模拟实现】
开发语言·c++·vscode·python·算法·leetcode
sweet丶3 小时前
适合iOS开发的一种缓存策略YYCache库 的原理
算法·架构
是宇写的啊3 小时前
算法—滑动窗口
算法
风筝在晴天搁浅3 小时前
代码随想录 509.斐波那契数
数据结构·算法
落落落sss4 小时前
java实现排序
java·数据结构·算法
fei_sun4 小时前
【数据结构】2018年真题
数据结构
limenga1024 小时前
支持向量机(SVM)深度解析:理解最大间隔原理
算法·机器学习·支持向量机