一道樂視網的面試題,求解答?

今天師姐在樂視網面試,遇到一道很難得演算法題,問了好多同學都不會,特地放到知乎上請各位大神解決!開始覺得是動態規劃,但是想了想好像也不是...


這是道數學題,大概說一下。

對於輸入為負數,結果與正數相等,忽略。

設輸入為n。

先求出一個p,使得 p*(p-1)/2 &< n &<= p*(p+1)/2 ,也就是說,1加到p剛好大於等於n,少一個就不行。

顯然,p是步數的最小值,而1加到p也正是p項和的最大值。

設 k=p*(p+1)/2-n ,就是最大值減去輸入值。

求p可以直接解二次方程,用double的14位精度應該夠了,或者做一點算術上的修正,複雜度和sqrt相同。

然後開始解步數。

顯然k&

當k=0時,答案步數就是p。

當k是偶數時,設k=2*r,則把1+2+3+...+p變成1+2+3+...-r+(r+1)+...+p即可,步數為p,顯然最優。

當k是奇數時,設k=2*r+1,再次分類。

觀察到p*(p+1)-n=k,而k是奇數,所以最大和於目標值奇偶性不同,又翻轉一個數(把1加到p的式子中的一個數從加變成減)奇偶性不變,因此根據p的奇偶性討論現在的最小步數。

當p是奇數時,p=2*q+1,p+1是偶數,不可能改變奇偶性,因此最少需要p+2步,式子為1+2+3+...-r+(r+1)+...+p+(p+1)-(p+2),在p*(p+1)/2的基礎上減掉2*r再減掉1,正好p+2步,顯然最優。

當p是偶數時,p=2*q,p+1是奇數,可以改變奇偶性,最小p+1步,式子為1+2+3+...-r+(r+1)+...+q-(q+1)+...+p+(p+1),在p*(p+1)/2的基礎上減2*r,減2*(q+1)再加上p+1=2*q+1,總共減掉2*r+1,正好p+1步。因為2*r+1=k&

p/2-1/2&>r,所以不會衝突。

這段討論都是O(1)。

討論邊際條件。

1. k偶時r=p, r=k/2&

2. k奇時r=p, r=(k-1)/2=k/2-1/2&3. p偶時q+1&>=p, 則p/2+1&>=p, p&<=2,對0,1,2可打表,步數為0,1,3。

4. k奇時r=0, k=1, 則不必翻轉,直接按照p分類討論即可。

至此,本題討論完畢。

總結,單個數字的複雜度完全由開平方算p決定,一般用FPU的話是帶大常數的O(1),應該比樓上O(nlogn)快。

代碼有空再貼,今天晚了。

以上。


想成是先跳1,2,3,……n步,這樣就到了frac{n(n+1)}{2}的地方;然後挑一些步數,把正著跳變成反著跳,每一次減少的數是2k。由於我們把一個正跳變成反跳,只能減少偶數步,所以最開始的總和frac{n(n+1)}{2}必須要跟x的奇偶性相同。這個表達式的奇偶性取決於n對4取模的結果,餘0、餘3的時候是偶數,餘1、餘2的時候是奇數。分別可以寫成:

2k(4k + 1) = 8k^2 + 2k

(4k+1)(2k+1) = 8k^2 + 6k + 1

(2k+1)(4k+3) = 8k^2 + 10k + 3

(2k+2)(4k+3) = 8k^2 + 14k + 6

我們再來考慮要回退的數的範圍。為了方便,我們記前面的表達式frac{n(n+1)}{2} = S(n)

如果我們挑了一個奇數,它:

  1. 位於S(4k+1)與S(4k+2)之間,於是相應的n至少應當是4k+2。我們要回退的範圍是0到4k中的偶數。回退一個數足夠了。
  2. 位於S(4k+2)與S(4k+5)之間,相應的n至少應當是4k+5。要回退的範圍是0到12k + 10中的偶數。這時候一個就不夠了,6k+5不在範圍內……但是,4k+3和2k+2怎麼樣?如果更小的話,自然也可以表示成4k+3和相應數的和,或者用單個數。

如果我們挑出了一個偶數,它:

  1. 位於S(4k)與S(4k+3)之間,於是相應的n至少應當是4k+3,要回退的範圍是0到12k+4中的偶數。4k+2,2k,兩個數剛好。更小的數自然也可以表示。
  2. 位於S(4k+3)與S(4k+4)之間,於是相應的n至少應當是4k+4,要回退的範圍是0到4k+4中的偶數。一個數足夠了。

結論:只要選出符合條件的最小的n,就一定可以跳到這一點上。符合條件是指:S(n) &>= x,且x為奇數是n = 4k + 1或4k + 2,x為偶數時n = 4k + 3或4k + 4。

求n的方法自然是求根公式:

n_0 = lceil frac{-1 + sqrt{1 + 8x}}{2} 
ceil

這裡要小心處理的一個坑是當1 + 8x是完全平方數的時候,整個表達式算出的結果是個整數,如果舍入誤差處理不好,往上進了1,就貽笑大方了……所以算出結果之後可以帶回到n(n+1) &>= 2x的表達式當中,檢驗n0和n0-1各自是否符合條件。算出n0之後,再根據x的奇偶性和n0對4取模的結果調整一下就可以輸出了。


最簡單粗暴的方法:bfs…

下面是數學方法,可以視為對@王遠答案的補充,因為我覺得他寫的不夠直觀

首先引入一條引理:1,2,3...p中部分數的和與1到p(p+1)/2之間的整數存在雙射關係,且兩者相等。下圖是p=4時的例子

設走p步後到達位置x(p)

則x(p)=a1*1+a2*2+…+ap*p,其中ai為係數要麼取1要麼取-1,取不同的係數對應不同的行動路徑。

令sum(p)=1+2+…+p,k(p)=sum-x

易知k是個偶數

那麼我們到到達目的地x0隻需保證sum(p)&>x0且k(p)是個偶數,在這個條件下找最小步數,有如下流程

步驟1:取整數p滿足

p(p-1)/2&步驟2:計算k=sum(p)-x0

步驟3:若為偶數,則最小步數為p;反之,p=p+1,跳回步驟2(注意此時計算k只需令k=k+p+1即可)

這裡有個問題,我們通過這個演算法得到最小步數p,但我們怎麼保證一定存在一組係數ai使x(p)=x0,即存在一條行動路徑使得p步後可以到達目的地x0。這時,引理就起作用了。

令r=k/2,因為0&<=r&

我感覺我自己講的也好複雜…歡迎大家吐槽


負數可以轉化成等價的正數情況。然後討論正數。

這個問題等價於序列 ?1?2?3?4...?n=k ,?代表正負號,求最小的n。

設a為其中正數項的和,b為負數項和。那麼

a-b=(1+n)*n/2

a+b=k

兩式相減得

-2b=(1+n)*n/2-k&>=0

對於公式 (1+n)*n/2-k要滿足兩個條件

1.值大於等於0

2.值是2的倍數

做法就是枚舉,n從1開始枚舉,當滿足上訴兩個條件就停止。

時間複雜度目測sqrt(n)

還有更快的,先在O(1)時間裡找到讓等式小於等於0的最大n,

然後再從這個n開始枚舉。

最後我敢說這是從ACdreamers的博客里看到的原題(UVA10025)QwQ

附鏈接(逃

數學經典題目


經過觀察,走 n 步之後能走到的長度是一個差為2的等差數列。

比如:

走1步,1=1,可能的目標是 {-1,1}

走2步,1+2 = 3, {-3,-1,1,3}

走3步,1+2+3=6, {-6,-4,-2,0,2,4,6}

先令 x = abs(x)

設解為n,令y = n(n+1)/2,若 y &> x,且 x 與 y 奇偶性相同,則 n 就是解了吧。

譬如,x = 7。

則n = 5, 此時y = 15。

x = 0 -1 + 2 - 3 +4 + 5 = 7

編程細節不討論了。


勉強算O(1)?

#include &
#include &
int minStep(int x) {
if (x==0) return 0;
if (x&<0) x=-x; int n=sqrt(2*x); while ((n+1)*n/2-x1 || (n+1)*n/2&


沒做出來,es6的bfs留下當參考吧

function bfs(x){
let m=new Set([0]);
for(let i=0;;i++){
let k=new Set();
for(let j of m){
if ((j+i)==x) return i;
if ((j-i)==x) return i;
k.add(j+i);
k.add(j-i);
}
m=k;
}
}
&>
&> [200,300,40000].map(bfs);
[ 20, 24, 283 ]

看完高票答案後感覺思路確實好,補代碼.

function calc(x){
if (x&<0) x=-x; let n1=parseInt((1+Math.sqrt(8*x+1))/2,10); let x1=n1*(n1-1)/2 if (x1==x) return n1-1; let x2=x1+n1-x; if (!(x21)) return n1; if (!(n11)) return n1+1; return n1+2; } for(i=0;i&<1000;i++){ if (bfs(i)!=calc(i)) console.log(i) }


聲明:僅考慮正距離。

首先,反過來考慮一個問題:

使用跳躍x次能走過的哪些距離?

答案是:對於任意的0 le k le frac{x 	imes (x+1)}{2} ,只要k與x奇偶性相同,都可以到達。

首先S=frac{x 	imes (x+1)}{2}是跳躍x次能夠到達的最遠距離。

那麼對於S-2,僅需要在第一步時回跳即可,即S-(1)	imes 2

對於S-2N,都是可以找到組合實現回跳的N

(總能找到{1,...,x}的子集表示任意小於S的數字。)

基於以上結論,對於所需達到的距離k,我們只需要找到最小的x即可。

1:利用二次方程求解公式求出x0

x_0 = frac{sqrt{1+8k}-1}{2}

double x0=Math.ceil((Math.sqrt(1+8*k)-1)/2);

2:奇偶性判斷

如果k和S=frac{x_0 	imes (x_0+1)}{2}奇偶性不同,則需要修正x0

if(k % 2 == 0){
if(x0 % 4 == 1){
x0 += 2;
} else if (x0 % 4 == 2){
x0 += 1;
}
}else{
if(x0 % 4 == 0){
x0 += 1;
} else if (x0 % 4 =3){
x0 += 2;
}
}


一開始覺得很難,覺得自己很水。。。。後來洗澡的時候想了一下,居然想出來答案了,真是覺得自己萌萌噠。

答案樓上已經說得很清楚了,我簡單地說說:

1.螞蟻最少跳多少步?

答:螞蟻一直往前跳,直到跳過「輸入數據」位置(跳了p步)。螞蟻的最短步數為p或者p+1。

2. 有沒有比p少的步數?

答:螞蟻一直往前跳都跳不到「輸入數據」,比p少絕壁不可能。

3. 為什麼第p步一定能剛剛好跳到「輸入數據」?

答:螞蟻一直往前跳p步,跳到M處。

假設螞蟻第1步往後跳,其他都往前跳,那麼就能跳到M-2*1處。

假設螞蟻第2步往後跳,其他都往前跳,那麼就能跳到M-2*2處。

假設螞蟻第1和2步往後跳,其他都往前跳,那麼就能跳到M-2*(1+2)處。

所以理論上螞蟻能跳到任何一個「輸入數據」的地方,只要控制好向後步數x,就能得到M-2*x=任何數(與M相差2,4,6,8等等任何偶數的數)。

如果「輸入數據」與M相差是奇數,則再往前跳一次,重複上面的過程。也就是p+1步。


我小學的時候,去參加南師附中江寧分校的小升初3+3班的考試,數學卷就有這道題(;一_一)


可以這樣想,如果沒有後跳的話,跳躍過程是一個1~n的求和過程,即Sigma i = x

現在過程中加入了後跳,所以上面的求和式中有某些元素會變成負,由正變負相當於減2k,因此上式可改為Sigma i  - even = x, 即1~n的和減去一個偶數後等於x

所以這個問題會有兩種情況:

1. Sigma i = x

2.Sigma i -even = x

換句話說,不斷的求1~n的和,然後第一個滿足上面兩種情況之一的就是所需的解,代碼的話這樣應該就可以了,注意x可以為負,不過負數只表示方向變化,並不影響思路

class Solution:
def JumpSteps(self, x):
s = 0
i = 0
steps = 0

stop = False

if x &< 0: x = -x if x == 0 or x == 1: return x while not stop: i += 1 s += i steps += 1 # print s, " ", steps if (s - x) &>= 0 and (s - x) % 2 == 0:
stop = True

return steps


大號被禁言了換小號來重新答一發

int jumpTo(long x) {

if (x &< 0) x = -x;

long sum = 0;

int n = 1;

for(; sum &< x; n++) sum += n;

//這裡執行完了以後sum = n(n - 1)/2

//並且滿足條件sum &>= x

//sum和x奇偶性相同,這裡很多答主都指出了,雖然我大號答的時候並沒有多少人指出來

if ((sum - x) 1 == 0) return n - 1;

//奇偶性不同的話,就要看下一個,那麼要找一個奇數n才可以,這裡還是有人以為return n就可以了,拿衣服

return n | 1;

}

我這個本來是第四個答案吶…………好桑心


第一印象:如果x大於0,可以至多2x步解決問題,先向後跳再向前跳,會前進1個單位,重複x次可以到達x處。

--------------------------------------------------------

如果採用計算機變成可以這樣轉換問題:一個從1開始的連續數字組成的累加算式,每個數字的符號待定(正號或者符號),等式右邊是目標坐標的值。如果等式成立,那麼答案找到。正號代表朝著x的方向,符號表示反向。

編程實現步驟如下:

1. 連續數字為從1到x(x跳最遠能夠等於或超過目標坐標,但x-1跳不能達到目標坐標)

2. 遍歷所有數字元號的組合。等式成立則結束,返回答案;否則下一步

3. 連續數字增加1個。如果連續數字超過2x則結束,沒有找到答案;否則回到第一步

根據之前的分析,不可能沒有答案,最多2x步。

--------------------------------------------------------

看來難點在於如何用最少的步數達到目的,以及如何最快找到最小的步數。

根據數學推導不難驗證以下結論:

x步最遠可以走到S(x),註:S(x)=(x^2+x)/2,當目標處於這些點上時可以不用浪費跳步。其餘的點必須有不同方向的跳步組成。

x步中如果只有一步走反向,那麼可以到達的點為S(x)-2k,k代表反向的距離,值為從1到x中任意一個。點的範圍是S(x-2)-1到S(x-2)-2。

如果增加兩步,可以走到S(x)+1或者S(x)-1。走法分別是-(x+1)+(x+2),+(x+1)-(x+2)。

x步最多增加兩步,就可以覆蓋所有從S(x-1)到S(x)上的點。

因此之前的程序可以簡化了,直接計算得出結論。

步驟如下:

1. 計算出x(x跳最遠能夠等於或超過目標坐標,但x-1跳不能達到目標坐標)

2. 如果目標和(x^2+x)之差為偶數或者0,可以直接得出反方向的那一步,其餘都為正向;

3. 如果目標和(x^2+x)之差為奇數,先計算差減一的反方向的那一步,然後-(x+1)+(x+2)調整。

這個方法很快,但有可能不是最優,有目標可能不需要多兩步。但是可以接受了。

--------------------------------------------------------

如果你要求極致,好吧讓我們繼續做推導

根據數學推導不難驗證以下結論:

如果x是偶數,那麼x+1步中只有一步反向所覆蓋的點中會覆蓋S(x-1)到S(x)之間所有S(x)-2k+1的點。

因此可以優化上一次的程序第3步如下:

3. 如果目標和(x^2+x)之差為奇數且x是偶數,步數加1,計算得出反方向的那一步,其餘都為正向;

4. 如果目標和(x^2+x)之差為奇數且x是奇數,先計算差減一的反方向的那一步,然後-(x+1)+(x+2)調整。

至此,找到最優解:)

--------------------------------------------------------

還沒有結束,能找到所有的最優解嗎?答案當然是能,但是怎麼樣最快呢?歡迎大家繼續討論。


問題可以簡化為pm1pm2pm3pm4pmcdotspm n=k,求n的值

因為每次只能向前或者向後跳n+1個單位,所以我們只能先找到後面可以取到的最大值,即k=1+2+3+4+cdots+n然後通過改變數字前面的正負號使k為要求的數值,可以概述為向後求最大然後向前取整,但向前取的時候只能使值k-2n為偶數(因為把一個值由正改為負時相當於減去2倍的這個值),所以減的值只能是偶數

由上可知:依次向後找值為n時的最大和sum(n)=1+2+3+4+cdots+n,使其與所求值k的差為偶數即可:(sum(n)-k)\%2==0k為題目所給的值,n為所求的步數

#include &
using namespace std;

int main()
{
int k;
int sum,n,s;
while(cin&>&>k,k)
{
sum=1;
n=1;
while(sum&


剛上大一,,,剛學計算機,,,請各位大神幫忙看看可行否,,,算了幾個簡單的值,都是對的。。。


bfs可以沒啥說的

但我覺得

dp也可以

跳了i步了,當前位置是j,下次前跳為1,後為0

dp[i+1][j+i+1][0] = dp[i][j][1];

dp[i+1][j+i+1][1] = dp[i][j][1];

dp[i+1][j-i-1][0] = dp[i][j][0];

dp[i+1][j-i-1][1] = dp[i][j][0];


送分題 1 +/- 2 +/- 3 …

由於局部最小解(n)是 1-2+3 …=n(每次遞增1)所以全局最優解小於等於局部最小解2n

全局可能最優解(m) 1+2+3...n=m是符合全為+或- 所以全局最優解大於等於這個m = (n+n^2)/2

n&>= x &>= m

證出n&>3時有一般解

(y1,y2)=(x+1-n+n1)/2

n1為小於n的最大的m

y為設為-的數 可能是1個也可能是2個取決於右邊的奇偶性

O(1)複雜度

偽dp問題


bfs簡單粗暴


只考慮位置的絕對值。

先求始終向正向到達或超過所需步數n。

如果此時離目標距離為偶數,則n為所求。

否則如果n為偶數,則n+1為所求。

否則n+2為所求。


寬度遍歷嘛?


推薦閱讀:

如果讓你清洗西雅圖市所有的窗戶,你索價多少?
從HR的角度看,面試有哪些注意事項?
如何成為一名好的面試官?

TAG:演算法 | 面試問題 | 樂視網信息技術北京股份有限公司 | 面試難題 |