面试手撕算法题--下一个排列

前言

面试官描述这个题的时候,我就感觉似曾相识似乎做过,面完以后到leetcode找到原题恨不得给自个儿来一下子,的确,当时调api爽了,然后呢面试被拷打了啊,我想不起来这个api具体怎么解决这个题目的底层原理,只能 自信的 给面试官来了一套暴力解法,然后面试官还温柔的好心引导我怎么做,但是我还是没搞定,最后面完之后邮件发给他具体代码,以下如图,暴力解法4ms,优化正解0ms。
面试手撕算法题--下一个排列_第1张图片

一、题目详情

整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。

例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。
整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。

例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。
类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。
而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。
给你一个整数数组 nums ,找出 nums 的下一个排列。

二、解题思路与代码

理解题目如下:
给定整数数组的一个排列,返回刚好比上一个排列大的下一个排列。
就是将其所有成员以序列或线性顺序排列后其整数的下一个字典序更大的排列
例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。
其排列后组合的大小排序为123,132,231,312,所以返回132

粗解思路:
1、把所有的排列列出来存储成一个数组
2、对该数组进行排序
3、返回给定数组的下一个排列值

优化思路:
1、从右向左扫描,找到第一个i 2、最右边开始找到右边第一个大于这个数的数(也就是比它大的最小数),进行交换
3、从i+1开始往后的位置都翻转

ps: 面试时是直接描述了题目在Dev里做的,我直接用string存了做的,但是整数数组也同理,同样的思路,代码变化不大,具体的可以在 :https://leetcode.cn/problems/next-permutation/ 里看原题。

#include 
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
using namespace std;

// 暴力思路求解 
string nextMaxNum1(string& str){
	string str1 = str;//临时存储 
	vector<string> ans;
	do{
		ans.push_back(str1);
//		cout<
	} while(next_permutation(str1.begin(), str1.end()));//不断存储下一个排列 
	sort(ans.begin(), ans.end());//排序 
	int i = 0;
	for(; i < ans.size(); i++){
		if(ans[i] == str) break;
	}
	return ans[i+1];//找到的下一个最大的值返回 
}

// 优化思路求解 
string nextMaxNum2(string& str){
	int len = str.size();
    if(len <= 1)
        return str;
    int i = len - 2;
    while(i >= 0 && str[i] >= str[i+1]){//找到第一个i
        i--;
    }
    if(i >= 0){
        int j = len - 1;
        while (j >= 0 && str[i] >= str[j]) {//找到右边第一个大于这个数的数
            j--;
        }
        swap(str[i], str[j]);//交换 
	}	
   	reverse(str.begin() + i + 1, str.end());
    return str;
}

int main(){
	string arr = "12345";
	cout<< nextMaxNum1(arr) << endl;//解法1 
	
	cout<< nextMaxNum2(arr) << endl;//解法2 
	return 0;
}

后记

官方曰:该优化方法支持序列中存在重复元素,且在 C++ 的标准库函数 next_permutation 中被采用。
意思就是 next_permutation 底层就是这样干的?哇呀呀呀,以后刷题一定不要偷懒啊,我有时面对能够调api或者取巧解决的方法,就没有深入研究这个题目最优解法,必须反省啊!要做一个题目,就要把这个题目研究透彻!!!

你可能感兴趣的:(数据结构与算法,算法,面试,职场和发展)