面试题----寻找比一个N位数大的“下”一个数

  1. 题目描述

      写出一个算法,实现如下功能:

给定一个N位数字组成的数,找出比这个数大的由相同数字组成的下一个数

例如:如果数字为 25468, 则结果为25486 如果数字为 21765, 则结果为 25167 如果数字为 54321, 则结果为 54321 (因为没有比这个数大的相同数字组成的值)

   

     2.问题分析

  • 因为N是一个没有范围的数,因此在解决此题时排出用N-位整数作为输入,而是用字符串来处理
  • 若存在有连续数字是相同的应该如何处理?
  • 观察例子可以得到如下思路

     一个N数如83557761,从右往左,找到当前位置上的数比它左边的数大为止(相等也要继续),即找到左边第一个7,比5大,得到7761,逆序为1677,然后从左往右找到第一个比5大的数6,交换5和6,即得到83561577。

     3.此算法一般性讲解

     把N位数分为两部分前i位和后N-i位,其中后N-i位从右往左是不减的(要么递增,要么相等),因此,不管怎样调这N-i,数都不会增大。按前面的分法,第i位一定比第i+1位小,也可能比第i+2位小,以此类推,找到第i+j位数,它比第i位数大,但是第i+j+1位数比第i位数小,交换第i位和第i+j位,然后提取i+1到第i+j-1这部分数字和第i+j+1到第N位的数字,这两部分分别逆序之后交换位置放置即可。结合例子可以理解。

    

      4.代码和注释

 1 #include<iostream>
 2 #include<string>
 3 #include <algorithm> 
 4 using namespace std;
 5 
 6 
 7 int main()
 8 {
 9     string digit;
10     cin >> digit;
11 
12     int len,i,j;
13     len = digit.length();
14     //N<=1直接输出
15     if(len <= 1)
16     {
17         cout << digit<<endl;
18         return 0;
19     }
20     //当digit中有连续的相同数字,在从右到左遍历时仍然继续遍历
21     for(i=len-1;i>=1;i--)
22         if(digit[i]>digit[i-1])break;
23 
24     //digit从右到左都是不减的,则不用调整
25     if(i==0)
26     {
27         cout << digit<<endl;
28         return 0;
29     }
30     //提取前i位
31     string pre = digit.substr(0,i);
32     //提取后N-i位
33     string end = digit.substr(i,len-i);
34     
35     reverse(end.begin(), end.end()); //逆序
36     
37 
38     int index = pre.length();
39     int num =pre[index-1]; 
40     for(j=0;j<end.length();j++)
41         if(end[j]>=num)break;
42 
43     //交换第i位和第i+j位
44     pre[index-1] = end[j];
45     end[j]=num;
46 
47     digit = pre+end;//合并即可
48 
49     cout<<digit<<endl;
50     return 0;
51 }
原文地址:https://www.cnblogs.com/LCCRNblog/p/3659437.html