【CODE】单调栈应用

目录

33. Search in Rotated Sorted Array

81. Search in Rotated Sorted Array II

153. Find Minimum in Rotated Sorted Array

154. Find Minimum in Rotated Sorted Array II

129. Sum Root to Leaf Numbers

670. Maximum Swap

321. Create Maximum Number

402. Remove K Digits

738. Monotone Increasing Digits


33. Search in Rotated Sorted Array

Medium

3871407Add to ListShare

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

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

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

Your algorithm's runtime complexity must be in the order of O(log n).

Example 1:

Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4

Example 2:

Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1
class Solution {
public:
    /*Runtime: 4 ms, faster than 80.01% of C++ online submissions for Search in Rotated Sorted Array.
    Memory Usage: 7.9 MB, less than 100.00% of C++ online submissions for Search in Rotated Sorted Array.*/
    int search(vector<int>& nums, int target) {
        int mid = 0;
	    for (int i = 1; i < nums.size(); i++) {
            if (nums[i] < nums[i - 1]) {
                mid = i; break;
            }
        }
        int left, right;
        if (mid - 1 < 0 || (nums[0] > target || nums[mid - 1] < target)) {
            left = mid; right = nums.size() - 1;
        }
        else if (nums[mid]<target || nums.back()>target) {
            left = 0; right = mid - 1;
        }
        else if(nums[0]==target) return 0;
        else if(nums[mid-1]==target) return mid-1;
        else if(nums[mid]==target) return mid;
        else if(nums.back()==target) return nums.size()-1;
        while (left <= right) {
            mid = left + (right - left) / 2;
            if (nums[mid] < target) left = mid + 1;
            else if (nums[mid] > target) right = mid - 1;
            else return mid;
        }
        return -1;
    }
};

81. Search in Rotated Sorted Array II

Medium

997417Add to ListShare

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., [0,0,1,2,2,5,6] might become [2,5,6,0,0,1,2]).

You are given a target value to search. If found in the array return true, otherwise return false.

Example 1:

Input: nums = [2,5,6,0,0,1,2], target = 0
Output: true

Example 2:

Input: nums = [2,5,6,0,0,1,2], target = 3
Output: false

Follow up:

  • This is a follow up problem to Search in Rotated Sorted Array, where nums may contain duplicates.
  • Would this affect the run-time complexity? How and why?
/*81. Search in Rotated Sorted Array II
二分法
Runtime: 8 ms, faster than 60.83% of C++ online submissions for Search in Rotated Sorted Array II.
Memory Usage: 8 MB, less than 100.00% of C++ online submissions for Search in Rotated Sorted Array II.*/
bool search(vector<int>& nums, int target) {
	int mid = 0;
	for (int i = 1; i < nums.size(); i++) {
		if (nums[i] < nums[i - 1]) {
			mid = i; break;
		}
	}
	int left, right;
	if (mid - 1 < 0 || (nums[0] > target || nums[mid - 1] < target)) {
		left = mid; right = nums.size() - 1;
	}
	else if (nums[mid]<target || nums.back()>target) {
		left = 0; right = mid - 1;
	}
	else return true;
	while (left <= right) {
		mid = left + (right - left) / 2;
		if (nums[mid] < target) left = mid + 1;
		else if (nums[mid] > target) right = mid - 1;
		else return true;
	}
	return false;
}

153. Find Minimum in Rotated Sorted Array

Medium

1639211Add to ListShare

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

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

Find the minimum element.

You may assume no duplicate exists in the array.

Example 1:

Input: [3,4,5,1,2] 
Output: 1

Example 2:

Input: [4,5,6,7,0,1,2]
Output: 0
class Solution {
public:
    /*Runtime: 4 ms, faster than 75.40% of C++ online submissions for Find Minimum in Rotated Sorted Array.
    Memory Usage: 7.9 MB, less than 100.00% of C++ online submissions for Find Minimum in Rotated Sorted Array.*/
    int findMin(vector<int>& nums) {
        int left=0,right=nums.size()-1;
        while(left<right){
            int mid=left+(right-left)/2;
            if(nums[mid]<nums[right]) right=mid;
            else if(nums[mid]>nums[right]) left=mid+1;
        }
        return nums[right];
    }
};

154. Find Minimum in Rotated Sorted Array II

Hard

683191Add to ListShare

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

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

Find the minimum element.

The array may contain duplicates.

Example 1:

Input: [1,3,5]
Output: 1

Example 2:

Input: [2,2,2,0,1]
Output: 0

Note:

class Solution {
public:
    /*当数组中存在大量的重复数字时,就会破坏二分查找法的机制,
    将无法取得 O(lgn) 的时间复杂度,又将会回到简单粗暴的 O(n),
    比如这两种情况:{2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 2} 和 
    {2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2},可以发现,
    当第一个数字和最后一个数字,还有中间那个数字全部相等的时候,
    二分查找法就崩溃了,因为它无法判断到底该去左半边还是右半边。
    这种情况下,将右指针左移一位(或者将左指针右移一位),略过一个相同数字,
    这对结果不会产生影响,因为只是去掉了一个相同的,
    然后对剩余的部分继续用二分查找法,在最坏的情况下,
    比如数组所有元素都相同,时间复杂度会升到 O(n).
    Runtime: 8 ms, faster than 59.29% of C++ online submissions for Find Minimum in Rotated Sorted Array II.
    Memory Usage: 8 MB, less than 100.00% of C++ online submissions for Find Minimum in Rotated Sorted Array II.*/
    int findMin(vector<int>& nums) {
        int left=0,right=nums.size()-1;
        while(left<right){
            int mid=left+(right-left)/2;
            if(nums[mid]<nums[right]) right=mid;
            else if(nums[mid]>nums[right]) left=mid+1;
            else right--;
        }
        return nums[right];
    }
};

129. Sum Root to Leaf Numbers

Medium

100730Add to ListShare

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.

An example is the root-to-leaf path 1->2->3 which represents the number 123.

Find the total sum of all root-to-leaf numbers.

Note: A leaf is a node with no children.

Example:

Input: [1,2,3]
    1
   / \
  2   3
Output: 25
Explanation:
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.
Therefore, sum = 12 + 13 = 25.

Example 2:

Input: [4,9,0,5,1]
    4
   / \
  9   0
 / \
5   1
Output: 1026
Explanation:
The root-to-leaf path 4->9->5 represents the number 495.
The root-to-leaf path 4->9->1 represents the number 491.
The root-to-leaf path 4->0 represents the number 40.
Therefore, sum = 495 + 491 + 40 = 1026.
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    /*Runtime: 4 ms, faster than 74.01% of C++ online submissions for Sum Root to Leaf Numbers.
    Memory Usage: 11.5 MB, less than 100.00% of C++ online submissions for Sum Root to Leaf Numbers.*/
    int sumNumbers(TreeNode* root) {
        stack<TreeNode*> s;
        int res=0;
        TreeNode *pre=NULL;
        string num="";
        while(root || !s.empty()){
            while(root){
                s.push(root);
                num+=(root->val+'0');
                root=root->left;
            }
            TreeNode *tmp=s.top();
            if(tmp->right==NULL || tmp->right==pre){
                s.pop();
                pre=tmp;
                root=NULL;
                if(tmp->right==NULL && tmp->left==NULL){
                    res+=stoi(num);
                }
                num=num.substr(0,num.size()-1);
            }else root=tmp->right;
        }
        return res;
    }
};

670. Maximum Swap

Medium

77255Add to ListShare

Given a non-negative integer, you could swap two digits at most once to get the maximum valued number. Return the maximum valued number you could get.

Example 1:

Input: 2736
Output: 7236
Explanation: Swap the number 2 and the number 7.

Example 2:

Input: 9973
Output: 9973
Explanation: No swap.

Note:

  1. The given number is in the range [0, 108]
class Solution {
public:
    /*Runtime: 0 ms, faster than 100.00% of C++ online submissions for Maximum Swap.
    Memory Usage: 7.9 MB, less than 100.00% of C++ online submissions for Maximum Swap.*/
    int maximumSwap(int num) {
        vector<int> n;
        vector<pair<int,int> > dp;
        while(num){
            n.push_back(num%10);
            num/=10;
        }
        dp.push_back(make_pair(n[0],0));
        for(int i=1;i<n.size();i++){
            if(n[i]>dp.back().first)
                dp.push_back(make_pair(n[i],i));
            else dp.push_back(dp.back());
        }
        for(int i=dp.size()-1;i>=0;i--){
            if(dp[i].first==n[i]) continue;
            int tmp=n[i];
            n[i]=dp[i].first;
            n[dp[i].second]=tmp;
            break;
        }
        
        int res=0;
        for(int i=n.size()-1;i>=0;i--){
            res=res*10+n[i];
        }
        return res;
    }
};

321. Create Maximum Number

Hard

558196Add to ListShare

Given two arrays of length m and n with digits 0-9 representing two numbers. Create the maximum number of length k <= m + n from digits of the two. The relative order of the digits from the same array must be preserved. Return an array of the k digits.

Note: You should try to optimize your time and space complexity.

Example 1:

Input:nums1 = [3, 4, 6, 5]nums2 = [9, 1, 2, 5, 8, 3]k = 5

Output:[9, 8, 6, 5, 3]

Example 2:

Input:nums1 = [6, 7]nums2 = [6, 0, 4]k = 5

Output:[6, 7, 6, 0, 4]

Example 3:

Input:nums1 = [3, 9]nums2 = [8, 9]k = 3

Output:[9, 8, 9]
#include"pch.h"
#include<iostream>
#include<vector>
#include<unordered_map>
#include<unordered_set>
#include<queue>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
/*321. Create Maximum Number
Runtime: 224 ms, faster than 22.70% of C++ online submissions for Create Maximum Number.
Memory Usage: 24.5 MB, less than 80.00% of C++ online submissions for Create Maximum Number.*/
vector<int> mergeVector ( vector<int> nums1, vector<int> nums2){
	//已经从nums1和nums2中取出元素了,现在混合,使之形成的整数最大
	vector<int> res;
	while (!nums1.empty() || !nums2.empty()) {
		//vector可以直接比较大小
		vector<int> &tmp = (nums1 > nums2) ? nums1 : nums2;
		res.push_back(tmp[0]);
		tmp.erase(tmp.begin());//tmp是nums1或nums2的地址,所以删除相当于删除nums1或nums2
	}
	return res;
}
vector<int> maxVector(vector<int> &nums, int k) {
	//在一个nums里面选出k个,组成最大的
	int drop = nums.size() - k;
	vector<int> res;
	for (auto num : nums) {
		while (drop > 0 && !res.empty() && res.back() < num) {
			res.pop_back();
			--drop;
		}
		res.push_back(num);
	}
	res.resize(k);
	return res;
}
vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
	/*从nums1中取i个元素,从nums2中取k-i个元素,i的范围:
	最小值:max(0,k-nums2.size())
	最大值:min(nums1.size(),k)*/
	int i;
	int n1 = nums1.size(), n2 = nums2.size();
	//这里需要使用n1和n2!!!
	int down = 0 > (k - n2) ? 0 : (k - n2);
	int up = n1 < k ? n1 : k;
	vector<int> res;
	for (i = down;i<=up; i++) {
		cout << i << endl;
		res = max(res, mergeVector(maxVector(nums1, i), maxVector(nums2, k - i)));
	}
	return res;
}
int main() {
	vector<int> nums1 = { 3,4,6,5 }, nums2 = { 9,1,2,5,8,3,5 };
	vector<int> res = maxNumber(nums1, nums2, 5);
	for (int i = 0; i < res.size(); i++) cout << res[i] << " ";
	return 0;
}

402. Remove K Digits

Medium

140679Add to ListShare

Given a non-negative integer num represented as a string, remove k digits from the number so that the new number is the smallest possible.

Note:

  • The length of num is less than 10002 and will be ≥ k.
  • The given num does not contain any leading zero

Example 1:

Input: num = "1432219", k = 3
Output: "1219"
Explanation: Remove the three digits 4, 3, and 2 to form the new number 1219 which is the smallest.

Example 2:

Input: num = "10200", k = 1
Output: "200"
Explanation: Remove the leading 1 and the number is 200. Note that the output must not contain leading zeroes.

Example 3:

Input: num = "10", k = 2
Output: "0"
Explanation: Remove all the digits from the number and it is left with nothing which is 0.
#include"pch.h"
#include<iostream>
#include<vector>
#include<unordered_map>
#include<unordered_set>
#include<queue>
#include<map>
#include<set>
#include<algorithm>
#include<string>
using namespace std;
/*402. Remove K Digits
n=num.size(),如果要去除k个,那么剩下n-k个,如何判断哪些数字应该去掉呢?
如果数字递增,那需要从后面移除最大的数字,
如果是乱序,单调栈:::只要发现当前的数字小于栈顶元素,就将栈顶元素移除,
开始遍历num的每一位,对于当前遍历到的数字c,进行while循环,
如果res不为空,且k>0,且res的最后一位>c,那么应该将res的最后一位移除,k-1
当跳出while循环后,将c加入res,最后将res的大小重设为n-k,
需要用一个while循环来去掉前面所有的0,然后返回时判断是否为空
Runtime: 4 ms, faster than 91.24% of C++ online submissions for Remove K Digits.
Memory Usage: 8.3 MB, less than 100.00% of C++ online submissions for Remove K Digits.*/
string removeKdigits1(string num, int k) {
	string res = "";
	int n = num.size(), keep = n - k;
	for (char c : num) {
		while (k && res.size() && res.back()>c) {
			res.pop_back();
			k--;
		}
		res.push_back(c);
	}
	res.resize(keep);
	while (!res.empty() && res[0] == '0') res.erase(res.begin());
	return res.empty() ? "0" : res;
}
/*Runtime: 4 ms, faster than 91.24% of C++ online submissions for Remove K Digits.
Memory Usage: 8.5 MB, less than 100.00% of C++ online submissions for Remove K Digits.*/
string removeKdigits(string num, int k) {
	string res = "";
	for (char c : num) {
		while(k && res.size() && res.back()>c){
			res.pop_back();
			k--;
		}
		if (res.size() || c != '0') res.push_back(c);
		//如果res为空,并且c为‘0’,那么这个c不放进去,在这一步杜绝了leading zero
	}
	while (res.size() && k) {
		res.pop_back();
		k--;
	}
	return res.empty() ? "0" : res;
}
int main() {
	cout << removeKdigits("10200",1);
	return 0;
}
 

738. Monotone Increasing Digits

Medium

34453Add to ListShare

Given a non-negative integer N, find the largest number that is less than or equal to N with monotone increasing digits.

(Recall that an integer has monotone increasing digits if and only if each pair of adjacent digits x and y satisfy x <= y.)

Example 1:

Input: N = 10
Output: 9

Example 2:

Input: N = 1234
Output: 1234

Example 3:

Input: N = 332
Output: 299

Note: N is an integer in the range [0, 10^9].

#include"pch.h"
#include<iostream>
#include<vector>
#include<unordered_map>
#include<unordered_set>
#include<queue>
#include<map>
#include<set>
#include<algorithm>
#include<string>
using namespace std;
/*738. Monotone Increasing Digits
Runtime: 0 ms, faster than 100.00% of C++ online submissions for Monotone Increasing Digits.
Memory Usage: 7.7 MB, less than 100.00% of C++ online submissions for Monotone Increasing Digits.*/
int monotoneIncreasingDigits(int N) {
	/*≤N的单调递增整数*/
	int res = 0;
	vector<int> num, st;
	while (N) {
		num.push_back(N % 10);
		N /= 10;
	}
	int start = -1;
	for (int i = num.size() - 2; i >= 0; i--) {
		if (num[i] < num[i + 1]) {
			start = i + 1;
			break;
		}
	}
	if (start == -1) {
		for (int i = num.size() - 1; i >= 0; i--) {
			res = res * 10 + num[i];
		}
		return res;
	}
	while (start < num.size()) {
		if (start + 1 < num.size() && num[start] > num[start + 1]) {
			num[start] -= 1; break;
		}
		else {
			start++;
		}
	}
	if (start == num.size()) { num[start - 1]--; start--; }
	for (int i = 0; i < start; i++) num[i] = 9;
	for (int i = num.size() - 1; i >= 0; i--) {
		res = res * 10 + num[i];
	}
	return res;
}
int main() {
	cout << monotoneIncreasingDigits(322);
	return 0;
}
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值