Array(12) -- Longest Consecutive Sequence, First Missing Positive, Buy and Sell Stock III, Find Mini

本文介绍了几种高效的算法设计技巧,包括寻找最长连续序列、找出旋转排序数组中的最小值、以及股票买卖的最佳时机等问题的解决方案。文章详细展示了如何利用数据结构如哈希表和动态规划来实现O(n)复杂度的算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Longest Consecutive Sequence

Given an unsorted array of integers, find the length of the longest consecutive elements sequence.

For example,
Given [100, 4, 200, 1, 3, 2],
The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4.

Your algorithm should run in O(n) complexity.


将vector转成set,任取set中的一个元素,分别向左右两边寻找序列,并不断删除已查找过的元素,直到set为空。

    int longestConsecutive(vector<int>& nums) {
        int maxLen = 0;
        unordered_set<int> s(nums.begin(), nums.end());	//普通set的查找是logn的,unordered_set是O(1)
        while(!s.empty()){
            int num = *(s.begin());
            s.erase(num);
            int right = num + 1;
            while(s.find(right) != s.end()) s.erase(right++);
            int left = num - 1;
            while(s.find(left) != s.end())  s.erase(left--);
            maxLen = max(maxLen, right - left - 1);
        }
        return maxLen;
    }



First Missing Positive

Given an unsorted integer array, find the first missing positive integer.

For example,
Given [1,2,0] return 3,
and [3,4,-1,1] return 2.

Your algorithm should run in O(n) time and uses constant space.

首先一点,如果数组中有k个正数,那么first missing positive 一定在[1, k+1]区间里。因此,我们把所有的正数放在数组中正确的位置(把nums[i]放在数组的nums[i] - 1位置);之后重新遍历数组,遇到的第一个value != i + 1的数,即为first missing positve.
    int firstMissingPositive(vector<int>& nums) {
        for(int i = 0; i < nums.size(); i++){
            while(nums[i] > 0 && nums[i] <= nums.size() && nums[nums[i]-1] != nums[i]){
                swap(nums[i], nums[nums[i]-1]);
            }
        }
        for(int i = 0; i < nums.size(); i++){
            if(nums[i] != i+1) return i+1;
        }
        return nums.size() + 1;
    }


Best Time to Buy and Sell Stock III

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete at most two transactions


四个变量代表该交易之后的余额,buy1st代表第一次买之后的余额。DP问题要找到状态和状态之间的转移方程。在该问题中,每次交易都会影响下一次交易的利润。所以状态应该是每次在某个价格进行buy和sell交易。

    int maxProfit(vector<int>& prices) {
        int buy1st = INT_MIN, sold1st = 0;
        int buy2nd = INT_MIN, sold2nd = 0;
        for(int i = 0; i < prices.size(); i++){
            sold2nd = max(sold2nd, buy2nd + prices[i]);
            buy2nd = max(buy2nd, sold1st - prices[i]);
            sold1st = max(sold1st, buy1st + prices[i]);
            buy1st = max(buy1st, -prices[i]);
        }
        return sold2nd;
    }


推广至at most K transaction的DP解法,at most K transaction 被 at most K-1 transaction的盈利情况影响。上述第一种解法将情况进行了更细致的刻画,在一趟扫描中同时记录K 和 K-1次的交易后的情况。

    int maxProfit(vector<int> &prices) {
        // f[k, ii] represents the max profit up until prices[ii] (Note: NOT ending with prices[ii]) using at most k transactions. 
        // f[k, ii] = max(f[k, ii-1], prices[ii] - prices[jj] + f[k-1, jj]) { jj in range of [0, ii-1] }
        //          = max(f[k, ii-1], prices[ii] + max(f[k-1, jj] - prices[jj]))
        // f[0, ii] = 0; 0 times transation makes 0 profit
        // f[k, 0] = 0; if there is only one price data point you can't make any money no matter how many times you can trade
        if (prices.size() <= 1) return 0;
        else {
            int K = 2; // number of max transation allowed
            int maxProf = 0;
            vector<vector<int>> f(K+1, vector<int>(prices.size(), 0));
            for (int kk = 1; kk <= K; kk++) {
                int tmpMax = f[kk-1][0] - prices[0];
                for (int ii = 1; ii < prices.size(); ii++) {
                    f[kk][ii] = max(f[kk][ii-1], prices[ii] + tmpMax);
                    tmpMax = max(tmpMax, f[kk-1][ii] - prices[ii]);
                    maxProf = max(f[kk][ii], maxProf);
                }
            }
            return maxProf;
        }
    }

Find Minimum in Rotated Sorted Array II

Follow up for "Find Minimum in Rotated Sorted Array":
What if duplicates are allowed?

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).


Find number in rotated sorted array的简化版,但存在重复数字时,两端相等时无法确定half与minumum的大小(即无法通过half确定minimum的位置),只能 right-- 逐个移动。

    int findMin(vector<int>& nums) {
        int left = 0, right = nums.size() - 1;
        int half = 0;
        while(left < right){
            half = (left+right) / 2;
            if(nums[half] < nums[right]) right = half;
            else if(nums[half] == nums[right]) right--;
            else left = half + 1;
        }
        return nums[left];
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值