對乙個正整數n,算得到1需要的最少操作次數

2021-07-11 13:17:00 字數 1293 閱讀 3532

實現乙個函式,對乙個正整數n,算得到1需要的最少操作次數。操作規則為:如果n為偶數,將其除以2;如果n為奇數,可以加1或減1;一直處理下去。

例子:

func(7) = 4,可以證明最少需要4次運算

n = 7

n-1 6

n/2 3

n-1 2

n/2 1

要求:實現函式(實現盡可能高效) int func(unsign int n);n為輸入,返回最小的運算次數。給出思路(文字描述),完成**,並分析你演算法的時間複雜度。

答:

int

func(unsigned int n)

假設n表示成二進位制有x bit,可以看出計算複雜度為o(2^x),也就是o(n)。

將n轉換到二進位制空間來看(比如7為111,6為110):

- 如果最後一位是0,則對應於偶數,直接進行除2操作。

- 如果最後一位是1,情況則有些複雜。

**如果最後幾位是???01,則有可能為???001,???1111101。在第一種情況下,顯然應該-1;在第二種情況下-1和+1最終需要的步數相同。所以在???01的情況下,應該選擇-1操作。

**如果最後幾位是???011,則有可能為???0011,???11111011。在第一種情況下,+1和-1最終需要的步數相同;在第二種情況下+1步數更少些。所以在???011的情況下,應該選擇+1操作。

**如果最後有更多的連續1,也應該選擇+1操作。

如果最後剩下的各位都是1,則有11時應該選擇-1;111時+1和-1相同;1111時應選擇+1;大於四個1時也應該選擇+1;

int

func(unsigned int n)

由以上的分析可知,奇數的時候加1或減1,完全取決於二進位制的後兩位,如果後兩位是10、00那麼肯定是偶數,選擇除以2,如果後兩位是01、11,那麼選擇結果會不一樣的,如果是*****01,那麼選擇減1,如果是*****11,那麼選擇加1,特殊情況是就是n是3的時候,選擇減1操作。

非遞迴**如下:

// 非遞迴寫法  

int func(int n)

count++;

} return

count;

}

另外一種寫法如下:

// 非遞迴寫法  

int func(int n)

return

count;

}

對乙個正整數n,求出n 中末尾0的個數。

對乙個正整數n,求出n 中末尾0的個數。輸入輸入有若干行。每一行上有乙個整數t,是測試資料組數,接著有t行,每一行包含乙個確定的正整數n n 1000000000 輸出對輸入行中的每乙個資料n,輸出一行,其內容是n 中末尾0的個數。輸入樣例 輸出樣例 3 3 0 100 24 1024 253 下邊...

乙個正整數表示為n個連續正整數之和(第1屆第2題)

問題描述 乙個正整數有可能可以被表示為 n n 2 個連續正整數之和,如 15 1 2 3 4 5 15 4 5 6 15 7 8 編寫程式,根據輸入的任何乙個正整數,找出符合這種要求的所有連續正整數序列。樣例輸入 15樣例輸出 1 2 3 4 5 4 5 6 7 8 題意很好懂,這個題第一直覺想到...

將乙個正整數L隨機拆分成n個正整數

隨機指定範圍內n個不重複的數 最簡單最基本的方法 param min 指定範圍最小值 param max 指定範圍最大值 param n 隨機數個數 public static int randomcommon int min,int max,int n int result new int n i...