1. 程式人生 > >2017.12.27 算法分析 貪心算法刪除數字求最小值問題

2017.12.27 算法分析 貪心算法刪除數字求最小值問題

算法 取出 -- 每次 for iostream 理解 後繼 code

1個n位正整數a,刪去其中的k位,得到一個新的正整數b,設計一個貪心算法,對給定的a和k得到最小的b;

一.我的想法:先看例子:a=5476579228;去掉4位,則位數n=10,k=4,要求的最小數字b是n-k=6位的;

1、先找最高位的數,因為是6位數字,所以最高位不可能在後5位上取到(因為數字的相對順序是不能改變的,假設如果取了後五位中倒數第5位的7,則所求的b就不可能是6位的了,最多也就是4位的79228)理解這點很重要!所以問題變成從第1位到第k+1(n-(n-k-1))取最小值,為什麽是k+1,可以自己想一下。在這裏就變成了

/54765/79228在斜杠中間選擇最小的數字!

2、這樣根據序號1,取得最小值4,那麽最高位就已經確定了是4;然後6位的數就變為還有5位要確定,同上邊的推理過程,次高位不可能取後4位中的任何數字,因為第一位確定了是第二位上的4,所以4之前的數字也不可能取到了(因為所求數字的相對順序不能發生變化),所以變為求54/7657/9228中,斜杠之內的數字的最小值,得到是5。3、然後取第三位數字54765/79/228,第三位取7;547657/92/28第四位取2;54765792/2/8,第五位只能是2;第六位就是8;則所得數字就是457228;

4、繼續想一個問題如果輸入的整數a是3346579228,同樣n=10,k=4;會遇到什麽樣的問題呢?同上邊的過程第一步:/33465/79228,此時區間內有兩個相同的最小值3,該用哪個值呢?很明顯應該選取第一個3,why?因為試想如果取第二個則,第二次就只能在4657中選擇最小值,而取第一個3,則可以再34657中取得3。

5、這個算法思路大概就是這樣的,算法具體該怎麽實現呢?首先我們要知道程序體要循環n-k次,因為只有這樣我們才能每次循環取出最小的數字;其次就是怎麽取區間內的最小值。我這裏用的是通過循環遍歷整個區間取得最小值,最關鍵的是確定區間的起始位置,第一次循環的位置最好確定就是1,結束位置就是k+1,第二次循環的起始位置是第一次取出的最小值的坐標值加1,結束位置是k+2;然後繼續記錄最小值的坐標值,以計算下一次的起始位置。

6、這是我的代碼:

#include<iostream>
using namespace std;
int main(){
    int num,k,n=0,a[100],x;
 cin>>num>>k;
 x=num;

//計算length(a);
 while(x>0){
  x=x/10;
  n++;
 }
 a[0]=0;

//將輸入的整形數字,存入定義的數組中;
 for(int i=n;i>0;i--)
 {
  int s=num%10;
  a[i]=s;
  num=num/10;
 }
 int j,p=0,minn[n-k+1],min,q;
 minn[0]=0;
 for(int i=1;i<=n-k;i++)//n-k次循環; 
 {
  min=a[p+1];

//定義q記錄坐標;min[]記錄每次所取的最小值
  q=p+1;
     for(j=p+1;j<=k+i;j++){
         if(a[j]<min)
      {
          min=a[j];
          q=j;
         }
     }
     p=q;
     minn[i]=min;
    }
    for(int i=1;i<=n-k;i++){
     cout<<minn[i];
 }
    return 0;
}

2017.12.27 算法分析 貪心算法刪除數字求最小值問題