程式設計師面試100題之十一 陣列迴圈移位

2021-08-26 03:28:21 字數 1537 閱讀 3086

設計乙個演算法,把乙個含有n個元素的陣列迴圈右移k位,要求時間複雜度為o(n),且只允許使用兩個附加變數。

不合題意的解法如下:

我們先試驗簡單的辦法,可以每次將陣列中的元素右移一位,迴圈k次。abcd1234--->4abcd123--->34abcd12--->234abcd1--->1234abcd。**如下所示:

rightshift(int *arr, int n, int k)

arr[0] = t;

}}

雖然這個演算法可以實現陣列的迴圈右移,但是演算法複雜度為o(k*n),不符合題目的要求,要繼續探索。

分析與解法

假如陣列為abcd1234,迴圈右移4位的話,我們希望達到的狀態是1234abcd。不妨設k是乙個非負的整數,當k為負整數的時候,右移k位,相當於左移(-k)位,左移和右移在本質上是一樣的。

解法一

大家開始可能會有這樣的潛在假設,k

仔細觀察迴圈右移的特點,不難發現:每個元素右移n位後都會回到自己的位置上。因此,如果k>n,右移k-n以後的陣列序列跟右移k位的結果是一樣的。進而可得出一條通用的規律:右移k位之後的情形,跟右移k』=k%n位之後的情形一樣,**如下所示:

rightshift(int *arr, int n, int k)

arr[0] = t;

}}

可見,增加考慮迴圈右移的特點之後,演算法複雜度降為o(n^2),這跟k無關,與題目的要求又接近了一步。但時間複雜度還不夠低,接下來讓我們繼續挖掘迴圈右移前後,陣列之間的關聯。

解法二

我們還是把字串看成有兩段組成的,記位xy。左旋轉相當於要把字串xy變成yx。我們先在字串上定義一種翻轉的操作,就是翻轉字串中字元的先後順序。把x翻轉後記為xt。顯然有(xt)t=x。

我們首先對x和y兩段分別進行翻轉操作,這樣就能得到xtyt。接著再對xtyt進行翻轉操作,得到(xtyt)t=(yt)t(xt)t=yx。正好是我們期待的結果。

分析到這裡我們再回到原來的題目。我們要做的僅僅是把字串分成兩段,第一段為前面m個字元,其餘的字元分到第二段。再定義乙個翻轉字串的函式,按照前面的步驟翻轉三次就行了。時間複雜度和空間複雜度都合乎要求。

假設原陣列序列為abcd1234,要求變換成的陣列序列為1234abcd,即迴圈右移了4位。比較之後,不難看出,其中有兩段的順序是不變的:1234和abcd,可把這兩段看成兩個整體,右移k位的過程就是把陣列的兩部分交換一下,變換的過程通過一下步驟完成:

1、逆序排列abcd:abcd1234--->dcba1234;

2、逆序排列1234:dcba1234--->dcba4321;

3、全部逆序:dcba4321--->1234abcd。

**如下所示:

reverse(int *arr, int b, int e)      //逆序排列

}rightshift(int *arr, int n, int k)

程式設計師面試100題之十五 陣列分割

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!一 題目概述 有乙個沒有排序,元素個數為2n的正整數陣列。要求把它分割為元素個數為n的兩個陣列,並使兩個子陣列的和最接近。假設陣列a 1.2n 所有元素的和是sum。模仿動態規劃解0 1揹包問題的策略,令s k,i 表示前k個元素中任意i個元素的和...

程式設計師面試100題之十二 求陣列中最長遞增子串行

寫乙個時間複雜度盡可能低的程式,求乙個一維陣列 n個元素 中最長遞增子串行的長度。例如 在序列1,1,2,3,4,5,6,7中,其最長遞增子串行為1,2,4,6。分析與解法 根據題目要求,求一維陣列中的最長遞增子串行,也就是找乙個標號的序列b 0 b 1 b m 0 b 0 解法一根據無後效性的定義...

程式設計師面試100題之十二 求陣列中最長遞增子串行

寫乙個時間複雜度盡可能低的程式,求乙個一維陣列 n個元素 中最長遞增子串行的長度。例如 在序列1,1,2,3,4,5,6,7中,其最長遞增子串行為1,2,4,6。分析與解法 根據題目要求,求一維陣列中的最長遞增子串行,也就是找乙個標號的序列b 0 b 1 b m 0 b 0 解法一根據無後效性的定義...