【算法训练记录——Day37】

1.leetcode_56合并区间

在这里插入图片描述
思路:排序,如果重叠,更新right 为max(right, curVal), 不重叠就加入res,需要单独考虑最后一次,因为每次都是在下一次遍历开始时判断是否加入res,因此 当 i==size()时,单独考虑

	static bool cmp(const vector<int>& v1, const vector<int>& v2){
        return v1 < v2;
    }
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        sort(intervals.begin(), intervals.end(), cmp);
        int right = intervals[0][1];
        int left = intervals[0][0];

        vector<vector<int>> res;
        // for(auto i : intervals) {
        //     cout << i[0] << " " << i[1] << endl;
        // }

        vector<int> tmp;
        tmp.push_back(left);
        for(int i = 1; i <= intervals.size(); i++) {
            if(i == intervals.size()) {
                tmp.push_back(right);
                res.push_back(tmp);
                break;
            }
            // cout << i << " " << right << " ";
            if(right < intervals[i][0]) {
                tmp.push_back(right);
                res.push_back(tmp);
                tmp.clear();
                left = intervals[i][0];
                right = intervals[i][1];
                tmp.push_back(left);
            } else {
                right = max(right, intervals[i][1]);

            } 
            cout << endl;;
        }
        return res;
    }

看题解:解法类似,但更简洁;每次都放入一组区间,每次遍历如果相交更新右边界,不相交插入新区间。
为啥没想到第二种,感觉思维受到了限制,跳脱不出来,只想着按部就班,只想着贪心每一步应该都是最优解。

	vector<vector<int>> merge(vector<vector<int>>& intervals) {
        sort(intervals.begin(), intervals.end(), [](const vector<int>& v1, const vector<int>& v2){ return v1 < v2;});

        vector<vector<int>> res;
        res.push_back(intervals[0]);

        for(int i = 1; i < intervals.size(); i++) {
            if(intervals[i][0] <= res.back()[1]) {
                res.back()[1] = max(intervals[i][1], res.back()[1]);
            } else {
                res.push_back(intervals[i]);
            }
        }

        return res;
    }
时间复杂度: O(nlogn)
空间复杂度: O(logn)

2.leetcode_738单调递增的数字

在这里插入图片描述
思路:没思路,看题解
小于等于n的 最大数字,首先想到,如果 nums[i] > nums[i+1], 例如76,那么递增的最大数字应该是(7-1)(9),nums[i]-1, nums[i+1] = 9;这时数字最大,如果从前向后遍历数组,nums[i]>nums[i+1]>nums[i+2],这种情况下,如果nums[i+1] 变为nums[i+1] - 1,那么nums[i]和nums[i+1]之间的关系又不满足,所以应该从后向前遍历数组

    int monotoneIncreasingDigits(int n) {
    	string s = to_string(n);
		int flag = s.size();
		for(int i = s.size() -1; i > 0; i--) {
			if(s[i-1] > s[i]) {
				flag = i;
				s[i-1]--;	
			}	
		}
        for(int i = flag; i < s.size(); i++) 
            s[i] = '9';
       	
		return stoi(s);
    }

3.leetcode_968监控二叉树在这里插入图片描述

思路:放哪里最合适,首先不能放在头节点和叶子节点,因为摄像机涵盖了上中下三层,放中间才能最大程度覆盖,那么就有两种放置方式,一种是自顶向下放置,这样的方式模拟一次会发现越往下可能产生的单独节点就越多,因为只要有一个节点未覆盖,就可能产生2^n的节点,因此选择自底向上放置,从叶子节点的上一个节点开始放置摄像机,这就要求我们先遍历叶子节点,选择左右根后序遍历,
怎么选择摄像头呢?遍历到左根节点,然后 递归看根节点的右节点的孩子?
看了下题解,对我很有帮助,用三个状态表示当前节点状态:未覆盖,有摄像头,已覆盖。
如果当前节点的左右节点有任一个处于未覆盖状态,那么curroot就应该放置摄像头,res++,如果子节点右任一个放置了摄像头,那么当前节点就应该是已覆盖,如果两个子节点都是已覆盖状态,那么curroot就是未覆盖状态。自底向上,如果根节点未覆盖 res++,之后返回res

	int res;
    int backtracking(TreeNode* root) {
        if(root == nullptr) {
            // cout << "-----4. "<< endl;
            return 2;
        }
        int left = backtracking(root->left);
        int right = backtracking(root->right);
        // cout << "-----begin: " << left << " " << right << endl;

        if(left == 0 || right == 0) {
            // cout << "-----1. " << left << " " << right << endl;
            res++;
            return 1;
        } else if(left == 2 && right == 2) {
            // cout << "-----2. " << left << " " << right << endl;
            return 0;
        } else if(left == 1 || right == 1) {
            // cout << "-----3. " << left << " " << right << endl;
            return 2;
        }
        return -1;
    }
public:
    int minCameraCover(TreeNode* root) {
        if(backtracking(root) == 0)
            res++;
        return res;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值