LeetCode日记20200220

本文深入探讨了LeetCode上的多个经典算法题目,包括寻找重复数、缺失的第一个正数、买卖股票的最佳时机等,通过详细代码解析,展示了双指针、DP、桶排序等技巧的应用。

LeetCode日记2020.2.20


双指针这种东西真是让人又爱又恨,DP也总是差些火候。

287 寻找重复数(mid)

转化为链表定位入环点的问题

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int slow = 0;
        int fast = 0;
        slow = nums[slow];
        fast = nums[nums[fast]];
        while(slow!=fast)
        {
            slow = nums[slow];
            fast = nums[nums[fast]];
        }
        int dup = 0;
        while(dup!=slow)
        {
            dup = nums[dup];
            slow = nums[slow];
        }
        return dup;
    }
};

也可以二分,统计左右区间的元素数目哪边多重复元素就在哪边然后继续二分。

41 缺失的第一个正数(hard)

桶排序(一个萝卜一个坑)

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int i=0, n=nums.size();
        while(i<nums.size())
        {
            if(nums[i]>0 && nums[i]<n+1 && nums[i]!=i+1 && nums[nums[i]-1] != nums[i])
                swap(nums[i], nums[nums[i]-1]);
            else
                ++i;
        }
        for(int j=0;j<n;++j)
        {
            if(nums[j] != j+1)
                return j+1;
        }
        return n+1;
    }
};

714 买卖股票的最佳时机(mid)

这种题关键在于DP问题的转化。

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        if(prices.size()<2)
            return 0;

        int cash = 0;
        int hold = -prices[0];
        for(int i=1;i<prices.size();++i)
        {
            cash = max(cash, hold+prices[i]-fee);
            hold = max(hold, cash-prices[i]);
        }
        return cash;
    }
};

11 盛水最多的容器(mid)

双指针!!!!

class Solution {
public:
    int maxArea(vector<int>& height) {
        int beg = 0, End = height.size()-1;
        int maxA = numeric_limits<int>::min();
        while(beg < End)
        {
            int area = (End - beg) * min(height[beg], height[End]);
            if(area > maxA)
                maxA = area;

            height[beg] < height[End] ? ++beg: --End;
        }
        return maxA;
    }
};

1338 数组大小减半(mid)

class Solution {
public:
    int minSetSize(vector<int>& arr) {
        map<int, int> se;
        vector<int> ps;
        for(auto i: arr)
        {
            if(se.find(i) == se.end())
            {
                se.insert(make_pair(i, ps.size()));
                ps.push_back(1);
            }
            else
                ++ps[se[i]];
        }
        sort(ps.rbegin(), ps.rend());
        int sum = 0, half = arr.size()/2;
        for(int i=0;i<ps.size();++i)
        {
            sum += ps[i];
            if(sum >= half)
                return i+1;
        }
        return 0;
    }
};

695 岛屿最大面积(mid)

class Solution {
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int m = grid.size(), n = grid.front().size();
        vector<vector<int>> adj(m*n);
        vector<int> flags(m*n, 0);
        int drs[4] = {-1, 0, 1, 0};
        int dcs[4] = {0, 1, 0, -1};
        for(int i=0;i<m;++i)
        {
            for(int j=0;j<n;++j)
            {
                if(grid[i][j] == 1)
                {
                    flags[i*n+j] = 1;
                    for(int k = 0;k<4;++k)
                    {
                        int row = drs[k] + i;
                        int col = dcs[k] + j;
                        if(row >=0 && row < m && col >= 0 && col < n && grid[row][col] == 1)
                            adj[i*n + j].push_back(row*n + col);
                    }
                }
            }
        }
        int maxC = 0;
        for(int i=0;i<flags.size();++i)
        {
            if(flags[i] == 1)
            {
                int sum = dfs(flags, adj, i);
                if(sum > maxC)
                    maxC = sum;
            }
        }
        return maxC;
    }

    int dfs(vector<int>& flags, const vector<vector<int>>& adj, int root)
    {
        int cnt = 1;
        flags[root] = 0;
        for(auto i: adj[root])
        {
            if(flags[i] == 1)
                cnt += dfs(flags, adj, i);
        }
        return cnt;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值