LeetCode581. Shortest Unsorted Continuous Subarray

581. Shortest Unsorted Continuous Subarray

Given an integer array, you need to find one continuous subarray that if you only sort this subarray in ascending order, then the whole array will be sorted in ascending order, too.

You need to find the shortest such subarray and output its length.

Example 1:

Input: [2, 6, 4, 8, 10, 9, 15]
Output: 5
Explanation: You need to sort [6, 4, 8, 10, 9] in ascending order to make the whole array sorted in ascending order.

Note:

  1. Then length of the input array is in range [1, 10,000].
  2. The input array may contain duplicates, so ascending order here means <=.

 题目:使得数组有序时,需要调整的最短子序列,返回子序列的长度。

解法参考https://leetcode.com/problems/shortest-unsorted-continuous-subarray/solution/

代码:https://github.com/abesft/leetcode/blob/master/581ShortestUnsortedContinuousSubarray/581ShortestUnsortedContinuousSubarray.cpp

1.先排序,后找子序列。

将原始的nums排好序得到nums_sorted,然后比对nums和nums_sorted中对应位置的元素,如果值不同,说明该位置的值在原始序列中是需要调整的,记录下这些元素所在的序号位置,找出最大最小的值,即可确定需要调整的最短子序列的长度。

#include <iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;

class Solution {
public:
	int findUnsortedSubarray(vector<int>& nums) {
		vector<int> sorted_nums(nums);
		sort(sorted_nums.begin(), sorted_nums.end());
		int left = nums.size(), right = 0;
		for (int i = 0; i < nums.size(); i++)
		{
			if (nums[i] != sorted_nums[i]) {
				left = min(left, i);
				right = max(right, i);
			}
		}
		return right - left > 0 ? (right - left + 1) : 0;
	}
};


int main()
{
	Solution sln;
	vector<int> testcase{ 1,3,4,3,5,3,2 };
	cout << sln.findUnsortedSubarray(testcase) << endl;
	std::cout << "Hello World!\n";
}

2.利用选择排序的思想

比较nums[i]和nums[j],i<j,如果nums[i] > nums[j],说明这两个位置是需要调整的,记录该位置序号,更新需要调整的子串的最左端和最右端。

#include <iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;


//Time Limit Exceeded
class Solution2 {
public:
	int findUnsortedSubarray(vector<int>& nums)
	{
		int left = nums.size(), right = 0;

		//selective sort
		for (int i = 0; i < nums.size(); i++) {
			for (int j = i + 1; j < nums.size(); j++) {
				if (nums[i] > nums[j]) {
					left = min(left, i);
					right = max(right, j);
				}
			}
		}
		return right - left > 0 ? (right - left + 1) : 0;
	}
};


int main()
{
	Solution2 sln;
	vector<int> testcase{ 1,3,4,3,5,3,2 };
	cout << sln.findUnsortedSubarray(testcase) << endl;
	std::cout << "Hello World!\n";
}

3.利用堆栈

首先考虑所求子串的左侧位置。堆栈中存放nums中有序序列的下标号,如果nums[i]比nums[stack.top()]值大,说明第i个值是无序的,需要找到nums[i]应该插入的位置,通过不断的和stack中的值比较可以得到,i值应该在的位置。注意要对整个序列的值都进行判断,如测试用例1,3,4,3,5,3,2。

所求子串的右侧位置思路同上,不同的地方在于对于nums序列是反向进行判断的。

#include <iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;

class Solution3 {
public:
	int findUnsortedSubarray(vector<int>& nums)
	{
		int left = nums.size(), right = 0;

		//保存的是有序序列的序号
		stack<int> index;
		for (int i = 0; i < nums.size(); i++) {
			while (!index.empty() && nums[index.top()] > nums[i]) {
				left = min(left, index.top());
				index.pop();
			}
			index.push(i);
		}
		stack<int> indexreverse;
		for (int i = nums.size() - 1; i >= 0; i--) {
			while (!indexreverse.empty() && nums[indexreverse.top()] < nums[i])
			{
				right = max(right, indexreverse.top());
				indexreverse.pop();
			}
			indexreverse.push(i);
		}

		return right - left > 0 ? (right - left + 1) : 0;
	}
};

int main()
{
	Solution3 sln;
	vector<int> testcase{ 1,3,4,3,5,3,2 };
	cout << sln.findUnsortedSubarray(testcase) << endl;
	std::cout << "Hello World!\n";
}

猜你喜欢

转载自blog.csdn.net/grllery/article/details/85416384