百度2019届算法岗秋招编程-逆序对数

题目

  • 给一个数组,可以将其中一个数字转化为0,求转化后的逆序对之和的最小值以及此时转化的下标。
  • 思路:这题最主要的就是求每个数字的到当前状态时的逆序对数(修改前和后),之前想的是用multiset存储数字,用upper_bound求比当前值大的数,用distance去计算逆序对的个数,但是后来发现distance在这种不可随机访问的容器中的时间复杂度为O(N),果断超时,只过了60%左右的case。
  • leetcode上有相似的题目,是求逆序对数的个数的,没有涉及到数字转换的问题:https://leetcode.com/problems/count-of-smaller-numbers-after-self/
  • 上面的最佳解法是构建pair数组,进行归并排序即可。
  • 可以将上面的思路引入到这里面来。先找到从左到右以及从右到左的逆序对的个数(从端点到当前),然后再逐个变成0,看是否可以减小逆序对的数量,记录最小数量以及最小值即可。
  • 关于上面leetcode题解有个比较好的讲解:https://www.cnblogs.com/ilovezyg/p/6877214.html

代码

	#include <cstdlib>
	#include <string>
	#include <iostream>
	#include <fstream>
	#include <sstream>
	#include <unordered_map>
	#include <unordered_set>
	#include <map>
	#include <set>
	#include <stdio.h>
	#include <numeric>
	#include <algorithm>
	#include <functional>
	#include <stack>
	#include <queue>
	#include <cmath>
	#include <vector>
	#include <memory>
	#include <memory.h>
	using namespace std;
	typedef long long ll;
	const int MOD = 1e9 + 7;
	typedef unsigned char uchar;
	
	// #define G_DEBUG
	// 定义unordered_set<pair<int,int>, pairhash> sets时会用到
	struct pairhash {
	public:
		template <typename T, typename U>
		std::size_t operator()(const std::pair<T, U> &x) const
		{
			return std::hash<T>()(x.first) ^ std::hash<U>()(x.second);
		}
	};
	
	void merge(vector<int>& count, vector<pair<int, int>>& nums, int start, int mid, int end)
	{
		int left = start, right = mid + 1;
	
		vector<pair<int, int>> helper(end - start + 1);
		int idx = 0;
		while (left <= mid && right <= end)
		{
			if (nums[left].first > nums[right].first)
			{
				count[nums[left].second] += (end - right + 1);
	
				helper[idx++] = nums[left++];
			}
			else
				helper[idx++] = nums[right++];
		}
		while (left <= mid)
			helper[idx++] = nums[left++];
		while (right <= end)
			helper[idx++] = nums[right++];
	
		copy(helper.begin(), helper.end(), nums.begin() + start);
	}
	
	void merge_sort(vector<int>& count, vector<pair<int,int>>& nums, int start, int end)
	{
		if (start >= end)
			return;
	
		int mid = (start + end) / 2;
		merge_sort(count, nums, start, mid);
		merge_sort(count, nums, mid + 1, end);
		merge( count, nums, start, mid, end );
	
	}
	
	
	int main()
	{
	
	#ifdef G_DEBUG
		// 调试使用
		ifstream file("data.txt");
		int N = 0;
		file >> N;
		vector<int> nums(N);
		for (int i = 0; i < N; i++)
		{
			file >> nums[i];
		}
	
		file.close();
	#else
		int N = 0;
		cin >> N;
		vector<int> nums(N, 0);
		for (int i = 0; i < N; i++)
		{
			cin >> nums[i];
		}
	
	#endif
		vector<pair<int, int>> pairs( N );
		for (int i = 0; i < N; i++)
		{
			pairs[i].first = nums[i];
			pairs[i].second = i;
		}
		vector<int> count_left(N, 0);
		merge_sort( count_left, pairs, 0, N-1 );
	
		vector<int> count_right(N, 0);
		
		for (int i = 0; i < N; i++)
		{
			pairs[i].first = -nums[N - 1 - i];
			pairs[i].second = N - 1 - i;
		}
		
		merge_sort(count_right, pairs, 0, N - 1);
	
		
	
		int before = 0;
		int min_idx = 0;
		int min_val = 0;
		for (int i = 0; i < N; i++)
			min_val += count_left[i];
		before = min_val;
		for (int i = 0; i < N; i++)
		{
			if (before + i - count_left[i] - count_right[i] < min_val)
			{
				min_val = before + i - count_left[i] - count_right[i];
				min_idx = i;
			}
				
		}
		
		cout << min_val << " " << (min_idx + 1) << endl;
	
	
	
		system("pause");
		return 0;
	}

猜你喜欢

转载自blog.csdn.net/u012526003/article/details/82860737