現在一單鏈表,要求用既省時間又省空間的方法找出倒數第m個元素。倒數第m個元素的定義是:當m=0時,返回最后一個元素。寫出設計思路和和C語言作答。給出以下代碼及函數聲明:兩種思路,前一種是我自己想的,
1,兩個指針,一個先遍歷m下停止,然后在兩個同時遍歷,這時另一個就到是倒數第m個了,稍微一點邏輯思維就可以搞定了,看代碼

element *FindMToLastElement(element *head, int m)
{
element *p1, *p2;
p1 = head;

for(int i = 0; i < m; ++i)
{
if(p1->next)
p1 = p1->next;
else
return NULL;
}
p2 = head;

while(p1->next)
{
p1 = p1->next;
p2 = p2->next;
}
return p2;
}

2,以前看過的阿諾的解答,整個長度m的循環鏈表遍歷,這樣的話,最后的m個元素都有了。
2,請說明下面這個程序的輸出,并給予解釋
int func(int i,int n)
{
return (i<n && printf("%d\n",i)) && !p(i+1,n)
|| printf("%d\n",i);
}
3 兩個整型數,不準用if 、switch 、?:等判斷語句求出兩者最大值,說出你的思路,能寫出代碼更好
關于2題,這里有個很好的解釋

已折疊
第二題其實也算一個比較常見的“智力”題。仔細觀察一下就可以發現return始終返回1,這樣理解里面的遞歸就比較容易了。

因為:i <n && printf("%d\n",i)) && !func(i+1,n) || printf("%d\n",i)

可以看做: exp1 && exp2 && exp3 || exp4,由于exp4是printf()的返回值,始終是一個非零值,所以不管前面的exp1,exp2,exp3的值什么,這個總表達式(exp1 && exp2 && exp3 || exp4)的值總是為1,也就是return始終返回1,也就是fun(i,n)的返回值始終為1.

再依次來看:
如果i >= n,則等價于 0 && printf("%d\n",i)) && !func(i+1,n) || printf("%d\n",i)
由于&&的短路性質,等價于 0 || printf("%d\n",i),即打印 i 的值。

如果i < n,則等價于 1 && printf("%d\n",i)) && !func(i+1,n) || printf("%d\n",i)
所以按順序執行過去,先打印一個 i ,隨后遞歸 !func(i+1,n),在遞歸里一樣處理,打印i + 1,進入第二次遞歸;打印i + 1 + 1,進入第三次遞歸。。。

一直到i = n為止,此時打印i,也就是打印n ,然后第一次返回,返回值為1。

在第一次返回的上下文中:i = n - 1, 由于func(i+1,n) 返回值恒等于1,所以!func(i+1,n)恒等于0,原來的總表達式等價于exp1 && exp2 && 0 || printf("%d\n",i),不管exp1和exp2的值為什么,這里都會執行最后的打印語句,而這里的i = n - 1,所以打印n - 1。

然后第二次返回,此時i = n - 2,打印n - 2。

第三次返回,打印 n - 3.

一直到i為最初的i,此時再打印一次i。
第3題有很多種解法,我來列舉一下
1,((a+b) + pow((a-b)*(a-b), 0.5))/2,從((a + b) + abs(a - b))/2而來,后者由于abs時加了判斷,所以用pow就顯得聰明了。
2,第二種解法一般用移位:
如果a>b,則a-b的二進制表示中最高位為0,(a-b)>>31 = 0;bigger = m[0];
如果a <b,則a-b的二進制表示中最高位為1,(a-b)>>31 = 1;bigger = m[1];
3,第三種解法主要借助&&和||來判斷,是受到二題的啟發
topic.csdn.net\u\20081030\16\1e4c9e2e-f704-4b24-b53e-169fc8246522.html
如果n為整數,則將它除以2
如果n為奇數,則將它加1或者減1
問對于一個給定的n,怎樣才能用最少的步驟將它變到1
例如
n=61
n-- 60
n/2 30
n/2 15
n++ 16
n/2 8
n/2 4
n/2 2
n/2 1
編程用c/c++
解答:
向4靠攏是有道理的,把數字用二進制表示,通過右移一位、加一、減一,讓他最終變成0(注意,看成變成0的更好理解一些,其實1變成0只是一個“減一”操作,就相差一步),就需要把所有的1消除掉。
怎么去掉1呢,右移不能消除一,只有加減一能夠,所以奇數時要考慮加還是減。
對于...01(2進制)這樣的情形,減一能夠消除1,加一不能,所以要減一;
對于...11,加一能夠至少消除一個1(比如...0111就是消除兩個1),減一只能消除一個1,那么對于...011的情形,應該加一還是減一呢?
答案應該是加一,因為向高位進的1可能會與更高位的1合并為1個連續的1串,使以后加一能夠一下子消除更多的1;
這里有一個例外,就是3(二進制11),因為更高位沒有1了,所以不能加一。