Leetcode(869)-重新排序得到 2 的冪


從正整數 N 開始,我們按任何順序(包括原始順序)將數字重新排序,注意其前導數字不能為零。

如果我們可以通過上述方式得到 2 的冪,返回 true;否則,返回 false

示例 1:

輸入:1
輸出:true

示例 2:

輸入:10
輸出:false

示例 3:

輸入:16
輸出:true

示例 4:

輸入:24
輸出:false

思路:這個題的重點是求出數字的全排列(以0開頭的除外),和數字是否2的冪

首先我們來總結下關於全排列。

這是一個c++函數,包含在頭文件<algorithm>里面,下面是一般用法的基本格式。

1  int a[];
2  do{
3      
4 }while(next_permutation(a,a+n));

STL提供了兩個用來計算排列組合關系的函數,分別是next_permutation和prev_permutation。首先我們必須了解什么是“下一個”排列組合,什么是“前一個”排列組合。考慮三個字符所組成的序列{a,b,c}。這個序列有六個可能的排列組合:abc,acb,bac,bca,cab,cba。這些排列組合根據less-than操作符做字典順序(lexicographical)的排序。也就是說,abc名列第一,因為每一個元素都小於其后的元素。acb是次一個排列組合,因為它是固定了a(序列內最小元素)之后所做的新組合。同樣道理,那些固定b(序列中次小元素)而做的排列組合,在次序上將先於那些固定c而做的排列組合。以bac和bca為例,bac在bca之前,因為次序ac小於序列ca。面對bca,我們可以說其前一個排列組合是bac,而其后一個排列組合是cab。序列abc沒有“前一個”排列組合,cba沒有“后一個”排列組合。

所以一般在用next_permutation函數之前,都將數字排序好,按照從小到大的順序。

下面來分析下next_permutation函數具體是怎么實現的。

  1. 從右往左掃描,發現第一個左鄰小於右鄰的數字,稱之為 PartitionNumber, 如上圖,6恰好是我們找到的 PartitionNumber .
  2. 依然從右到左進行掃描,發現第一個比 PartitionNumber 要大的數,稱之為 ChangeNumber.而7恰好是我們找到的 ChangeNumber ,需要注意的是,這樣的數一定是存在的,否則的話,就找不到所以的 PartitionNumber 了.
  3. 交換 PartitionNumber 和 ChangeNumber.這樣一步,會使得新的排列組成的數比舊的排列組成的數要大,當然,新數增長的幅度不一定是最小的.
  4. 交換之后,將當前ChangeNumber后面的數(或者原來PartitionNumber位置之后的數)從小到大排列一下,如此反轉之后,可以保證,新的排列組成的數的增長幅度在所有的可能中最小.
 template<calss BidrectionalIterator>
 bool next_permutation(BidrectionalIterator first,BidrectionalIterator last)
 {
     if(first == last) return false; /* 空區間 */
     BidrectionalIterator i = first;
     ++i;
     if(i == last) return false;  /* 只有一個元素 */
     i = last;                    /* i指向尾端 */  
     --i;
     for(;;)
     {
         BidrectionalIterator ii = i;
         --i;
         /* 以上鎖定一組(兩個)相鄰元素 */
         if(*i < *ii)           /* 如果前一個元素小於后一個元素 */
         {
             BidrectionalIterator j = last; /* 令j指向尾端 */
             while(!(*i < *--j));     /* 由尾端往前找,直到遇到比*i大的元素 */
             iter_swap(i,j);          /* 交換i,j */
             reverse(ii,last);        /* 將ii之后的元素全部逆序重排 */
             return true;
         }
         if(i == first)       /* 進行至最前面了 */
         {
            reverse(first,last);    /* 全部逆序重排 */
             return false;
         }
     }
 }

接着我們討論下,如何判斷一個數是2的冪。

我們知道,1個數乘以2就是將該數左移1位,而2的0次冪為1, 所以2的n次冪(就是2的0次冪n次乘以2)就是將1左移n位, 這樣我們知道如果一個數n是2的冪,則其只有首位為1,其后若干個0,必然有n & (n - 1)為0。(在求1個數的二進制表示中1的個數的時候說過,n&(n-1)去掉n的最后一個1)。因此,判斷一個數n是否為2的冪,只需要判斷n&(n-1)是否為0即可。

那如何判斷是2的多少次方呢

int log2(int value)   //遞歸判斷一個數是2的多少次方
{
 if (value == 1)
  return 0;
 else
  return 1+log2(value>>1);
}

下面附上本題的完整代碼

 bool reorderedPowerOf2(int n)
 {
      int i,j,k,tmp;
      vector<int> a;
      a.clear();
      while (n>0)
      {
        a.push_back(n%10);
        n/=10;
      }
      sort(a.begin(),a.end());
      do
      {
        if (a[0]==0) continue;
        tmp=0;
        for (i=0;i<a.size();i++)
          tmp=tmp*10+a[i];
      if((tmp&tmp-1)==0)return true;
      }while (next_permutation(a.begin(),a.end()));
      return false; 
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM