leetcode刷题记录(一)

格雷编码

知识点:数字逻辑,深度优先遍历,回溯,动态规划
解题思路:前排的大部分楼主都是利用格雷编码的性质,动态规划求解。如果没学过格雷编码的同学可能很难理解。
其实这道题也可以看成是图的搜索,利用深度优先搜索和回溯可以求解。用一个n维的数组存储当前数字的每一位,分别改变每一位,递归地搜索,最终可以找到一个可行解。

class Solution {
public:
    vector<int> list;
    vector<int> grayCode(int n) {
        if(n < 1)
        {
            list.push_back(0);
            return list;
        }
        vector<int> res;
        vector<int> bits(n, 0);
        vector<bool> marked(pow(2, n), false);
        dfs(n, bits, marked, res);
        return res;

    }

    bool dfs(int n, vector<int>& bits, vector<bool>& marked, vector<int>& res)
    {
        int number = bitToNum(bits);
        if (marked[number])
            return false;
        res.push_back(number);
        marked[number] = true;
        if (res.size() == pow(2, n))
        {
            return true;
        }

        for (int i = 0; i < n; i++)
        {
            int tmp = bits[i];
            bits[i] = (bits[i] + 1) & 0x1; //循环分别修改每一位
            if (dfs(n, bits, marked, res))
                return true; //如果找到解了就不必再继续搜索了,直接返回
            bits[i] = tmp;//记得改回来
        }
        res.pop_back();
        marked[number] = false; //回溯恢复原来的状态
        return false;
    }

    int bitToNum(vector<int> bits)
    {
        int res = 0;
        for (int bit: bits)
        {
            res = res * 2 + bit;
        }
        return res;
    }
};

作者:ppcat
链接:https://leetcode-cn.com/problems/gray-code/solution/shen-du-you-xian-sou-suo-hui-su-fa-qiu-jie-by-ppca/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

寻找旋转数组中的最小值

知识点:二分搜索
终止条件是num[mid] > num[mid+1],那么num[mid+1】就是最小值。
搜索规则:如果如果nums[mid] >= nunm[left]那么左半部分是有序数组,最小值再右半部分,left = mid + 1,反之,最小值在左半部分,right = mid - 1

class Solution {
public:
    int search(vector<int>& nums) {
        int left = 0;
        int right = nums.size() - 1;
        while (left <= right)
        {
            int mid = (right + left) / 2;
            if (nums[mid] > nums[mid+1])
                return mid + 1;
            if (nums[mid] >= nums[left]) //等号条件十分重要!!!有空debug看看为啥
                left = mid + 1;
            else
                right = mid - 1;
                
                
        }
        return left;
    }
};

搜索旋转排序数组

知识点:二分法
解题思路:
1.可以利用上题找到最小值,然后用target比较,可以决定在哪部分进行二分搜索
2. 直接二分法:
分两种情况讨论:有序数组在这左边;有序数组在右边

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1;
        while(left <= right)
        {
            int mid = (left + right) / 2;
            if (nums[mid] == target) 
                return mid;
            if (nums[left] <= nums[mid])
            { //有序数在左边
                if (target >= nums[left] && target < nums[mid])
                    right = mid - 1; //如果target在有序数组里,那么在有序数组内搜索
                else
                    left = mid + 1; //反之在无序数组里
            }
            else
            { //有序数组在右边
                if (target > nums[mid] && target <= nums[right])
                    left = mid + 1; 
                else
                    right = mid - 1;
                

            }
        }
        return -1;
    }
};

柱状图中的最大值

知识点:分治法,动态规划,递增栈
思路1:分治法
思路2:动态规划法
对于位置i,以i为中心的,向左边扫描,第一个小于heights[i]的位置x,向左边扫描,第一个小于heights[i]的位置y,面积是heights[i] * (y - x - 1)
思路3:递增栈

//动态规划法
class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int N = heights.size();
        if (N < 1)
            return 0;
        int lefts[N];
        int rights[N];
        lefts[0] = -1;
        rights[N - 1] = N;
        for (int i = 1; i < N; i++)
        {
            int dp = i - 1;
            while(dp >= 0 && heights[dp] >= heights[i])
                dp = lefts[dp];
            lefts[i] = dp;
        }

        for (int i = N - 2; i >= 0; i--)
        {
            int dp = i + 1;
            while(dp < N && heights[dp] >= heights[i])
                dp = rights[dp];
            rights[i] = dp;
        }

        int res = 0;
        for (int i = 0; i < N; i++)
            res = std::max(res, (rights[i] - lefts[i] - 1) * heights[i]);
        return res;
    }
};

其他思路的代码实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值