日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

面试题之发散思维能力:如何用非常规方法求1+2+···+n

發(fā)布時(shí)間:2024/8/23 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面试题之发散思维能力:如何用非常规方法求1+2+···+n 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
今天在《劍指offer》里看到了下面這樣一個(gè)簡(jiǎn)單且有趣的題,考察程序員的發(fā)散思維能力,前提是你對(duì)C++相關(guān)知識(shí)點(diǎn)熟悉,否則是想不出來(lái)方案的,分享給大家。 ? 題目:求1+2+···+n,要求不能使用乘除法、for、while、if、else、switch、case等關(guān)鍵字及條件判斷語(yǔ)句(A?B:C)。 點(diǎn)評(píng):這個(gè)問(wèn)題本身沒(méi)有太多的實(shí)際意義,因?yàn)樵谲浖_(kāi)發(fā)中不可能有這么苛刻的限制。但不少面試官認(rèn)為這是一道不錯(cuò)的能夠考查應(yīng)聘者發(fā)散思維能力的題目,而發(fā)散思維能夠反映出應(yīng)聘者知識(shí)面的寬度,以及對(duì)編程相關(guān)技術(shù)理解的深度。 ? 分析:通常求1+2+?···?+n有三種常規(guī)思路(1)循環(huán);(2)遞歸(需要用if語(yǔ)句或者條件判斷語(yǔ)句來(lái)判斷是繼續(xù)遞歸下去還是終止遞歸);(3)使用公式n*(n+1)/2。因?yàn)轭}目限制,這三種常規(guī)方案都不可行。那么如何用非常規(guī)方案求解該問(wèn)題呢?下面提供兩種解題思路,對(duì)應(yīng)四種解決方案,本質(zhì)上還是采用循環(huán)或遞歸的思路,只是寫法改變了。 ? 解題思路一:循環(huán)角度 基本思想:從循環(huán)角度思考。循環(huán)只是讓相同的代碼重復(fù)執(zhí)行n遍而已,我們完全可以不用for和while來(lái)達(dá)到這個(gè)目的。比如下面采用的構(gòu)造函數(shù)法。

方案一:利用構(gòu)造函數(shù)求解

具體方案:我們先定義一個(gè)類型,接著創(chuàng)建n個(gè)該類型的實(shí)例,那么這個(gè)類型的構(gòu)造函數(shù)將確定會(huì)被調(diào)用n次。我們可以將與累加相關(guān)的代碼放到構(gòu)造函數(shù)里。 實(shí)現(xiàn)代碼: class Temp { public:Temp() { ++N; Sum += N; }static void init() { N = 0; Sum = 0; }static unsigned int getSum() { return Sum; }private:static unsigned int N;static unsigned int Sum; };unsigned int Temp::N = 0; unsigned int Temp::Sum = 0;unsigned int sum_solution1(unsigned int n) {Temp::init();Temp *temp = new Temp[n];delete []temp;temp = NULL;return Temp::getSum(); } ? ? 解題思路二:遞歸角度 基本思想:從遞歸角度思考。根據(jù)題目限制我們不能在一個(gè)函數(shù)中判斷遞歸終止的條件,那么我們不妨定義兩個(gè)函數(shù):一個(gè)函數(shù)充當(dāng)原遞歸函數(shù)中遞歸的角色,另一個(gè)函數(shù)處理遞歸終止的情況,我們需要做的就是在兩個(gè)函數(shù)里二選一。從二選一我們很自然的想到布爾變量,比如值為true(1)的時(shí)候調(diào)用第一個(gè)函數(shù),值為false(0)的時(shí)候調(diào)用第二個(gè)函數(shù)。那如何將數(shù)值變量n轉(zhuǎn)換成布爾變量呢?解決方法就是對(duì)n連續(xù)做兩次取反運(yùn)算,即!!n,這樣非零的n就會(huì)轉(zhuǎn)換為true,0就轉(zhuǎn)換為false。 基于該思想有下面三種解決方案。 ?

方案二:利用虛函數(shù)求解

具體方案:用虛函數(shù)來(lái)實(shí)現(xiàn)函數(shù)的選擇。比如父類虛函數(shù)處理遞歸終止,子類虛函數(shù)實(shí)現(xiàn)遞歸累加,那么當(dāng)n不為0時(shí),調(diào)用子類函數(shù),n為0時(shí)調(diào)用父類函數(shù)即可完成計(jì)算。 實(shí)現(xiàn)代碼: class Base; Base* array[2];class Base { public:virtual unsigned int sum(unsigned int n){return 0;} };class Derived : public Base { public:virtual unsigned int sum(unsigned int n){return array[!!n]->sum(n - 1) + n;} };unsigned int sum_solution2(unsigned int n) {Base b;Derived d;array[0] = &b;array[1] = &d;return array[1]->sum(n); } ?

方案三:利用函數(shù)指針求解

具體方案:在純C語(yǔ)言的編程環(huán)境中,我們不能使用虛函數(shù),此時(shí)可以用函數(shù)指針來(lái)模擬,這樣代碼可能還更加直觀一些。 實(shí)現(xiàn)代碼: typedef unsigned int (*fun)(unsigned int);unsigned int sum_terminator(unsigned int n) {return 0; }unsigned int sum_solution3(unsigned int n) {fun f[2] = {sum_terminator, sum_solution3};return f[!!n](n - 1) + n; } ?

方案四:利用模板類型求解

具體方案:最后我們還可以讓編譯器來(lái)幫助完成類似于遞歸的計(jì)算。例如利用模板類型,以n作為模板參數(shù)。 實(shí)現(xiàn)代碼 template <unsigned int n> struct sum {enum value { N = sum<n - 1>::N + n }; };template <> struct sum<1> {enum value { N = 1 }; }; ? 說(shuō)明:sum<100>::N就是1+2+···+100的結(jié)果。該方法有明顯的缺陷,由于該計(jì)算過(guò)程是在編譯過(guò)程中完成的,因此要求輸入n必須是在編譯期間就能確定的常量,也就是我們不能動(dòng)態(tài)輸入n,這是最大的缺點(diǎn),而且編譯器對(duì)遞歸編譯代碼的遞歸深度是有限制的,也就是要求n不能太大。 綜合測(cè)試代碼: #include <iostream> using namespace std;unsigned int sum_solution1(unsigned int n); unsigned int sum_solution2(unsigned int n); unsigned int sum_solution3(unsigned int n); unsigned int sum_solution4(unsigned int n);unsigned int main() {unsigned int n;scanf("%d", &n);printf("sum_solution1(%d): %d\n", n, sum_solution1(n));printf("sum_solution2(%d): %d\n", n, sum_solution2(n));printf("sum_solution3(%d): %d\n", n, sum_solution3(n));printf("sum_solution4(%d): %d\n", 100, sum_solution4(n));return 0; }/************** solution 1 ***************/ class Temp { public:Temp() { ++N; Sum += N; }static void init() { N = 0; Sum = 0; }static unsigned int getSum() { return Sum; }private:static unsigned int N;static unsigned int Sum; };unsigned int Temp::N = 0; unsigned int Temp::Sum = 0;unsigned int sum_solution1(unsigned int n) {Temp::init();// Temp temp[] = new Temp[n];Temp *temp = new Temp[n];delete []temp;temp = NULL;return Temp::getSum(); }/************** solution 2 ***************/ class Base; Base* array[2];class Base { public:virtual unsigned int sum(unsigned int n){return 0;} };class Derived : public Base { public:virtual unsigned int sum(unsigned int n){return array[!!n]->sum(n - 1) + n;} };unsigned int sum_solution2(unsigned int n) {Base b;Derived d;array[0] = &b;array[1] = &d;return array[1]->sum(n); }/************** solution 3 ***************/ typedef unsigned int (*fun)(unsigned int);unsigned int sum_terminator(unsigned int n) {return 0; }unsigned int sum_solution3(unsigned int n) {fun f[2] = {sum_terminator, sum_solution3};return f[!!n](n - 1) + n; }/************** solution 4 ***************/ template <unsigned int n> struct sum {enum value { N = sum<n - 1>::N + n }; };template <> struct sum<1> {enum value { N = 1 }; };unsigned int sum_solution4(unsigned int n) {return sum<100>::N; // 必須指定常數(shù) } View Code

運(yùn)行結(jié)果:

大家還能想出其它的解決方案嗎?歡迎補(bǔ)充~~~ ------------------------------------分割線----------------------------------------- 2014.2.12更新: 感謝博客園網(wǎng)友張海拔的補(bǔ)充,提供了下面這個(gè)非常簡(jiǎn)單的解決方案: #include <stdio.h>int main(void) {int n;scanf("%d", &n);char a[n][n];printf("sum = %d\n", ((int)sizeof a + n)>>1);return 0; }

在Linux下用gcc測(cè)試的確可行,不過(guò)需要C99可變長(zhǎng)參數(shù)的支持,因此在微軟編輯器下是編譯不成功的。本文只從三種常規(guī)方案的循環(huán)和遞歸兩種方案提供解題思路,這里從公式n*(n+1)/2出發(fā),提供了第三種解題思路,不失為一種好的解決方案。

轉(zhuǎn)載于:https://www.cnblogs.com/lanxuezaipiao/p/3544963.html

總結(jié)

以上是生活随笔為你收集整理的面试题之发散思维能力:如何用非常规方法求1+2+···+n的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。