算法(一)-算法思想

一、算法思想介紹

常用的算法包含但不限于以下幾種:

  • 分治: 分而治之牍蜂,將問題拆解為形式相同子問題處理厂置,然后合并為原問題解陷虎。
  • 窮舉: 無差別例舉每一種可能解到踏。
  • 迭代: 不斷用變量的舊值推出新值。
  • 回溯: 按條件走尚猿,走不通就退回重新再走窝稿,回溯的核心在遞歸。
  • 遞歸: 函數(shù)調(diào)用自身來處理相同邏輯谊路。
  • 貪心: 將問題拆解為子問題來處理讹躯,每一步都先考慮當前最優(yōu)(貪心)選擇。
  • 動態(tài)規(guī)劃:將問題拆解為子問題來處理缠劝,整體問題的最優(yōu)解依賴各個子問題的最優(yōu)解潮梯,自下而上求解襟铭,需要記錄之前的所有局部最優(yōu)解锣尉。
二、經(jīng)典案例分析
1)二分查找 (分治)

題干:在一個有序數(shù)組中唆涝,在不增加空間復雜度的前提下脱羡,高效查找目標數(shù)萝究。

public static int binarySearch(int[] arr, int target, int low, int high) {
    if (target < arr[low] || target > arr[high] || low > high) {
        return -1;
    }
    int middle = (low + high) / 2;
    if (target < arr[middle]) {
        return binarySearch(arr, target, low, middle);
    } else if (target > arr[middle]) {
        return binarySearch(arr, target, middle, high);
    } else {
        return middle;
    }
}

注:這里用了遞歸來簡化邏輯。

2)雞兔共籠 (窮舉)

題干:一個籠子里關(guān)有雞兔共35頭锉罐,一共94只腳帆竹,籠中雞兔各有多少只?

public static void exhaustion(int head, int foot) {
    int chicken ;
    int rabbit ;
    for (int i = 0; i <= head; i++) {
       chicken = i;
        rabbit = head - i;
        if (2 * chicken + 4 * rabbit == foot) {
            System.out.println("chicken:" + chicken + "; rabbit:" + rabbit);
        }
    }
}
3)Fibonacci數(shù)列 (迭代)

題干:求Fibonacci數(shù)列:1脓规、1栽连、2、3侨舆、5秒紧、8、13挨下、21熔恢、34、…… 第N位元素值

public static int iteration(int n) {
    if (n == 0) {
        return 0;
    } else if (n == 1 || n == 2) {
        return 1;
    } else if (n > 2) {
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
    return -1;
}
4)八皇后問題 (回溯)

題干:將八個皇后放在棋盤上臭笆,沒有任何兩個皇后在同一行叙淌、同一列或者同一對角線上

static int count = 0;
static int size = 4;
public static void main(String[] args) {
    LinkedList<Location> arr = new LinkedList<>();
    traceBack(arr, 0, 0);
    printResult(arr);
    System.out.println("八皇后共有: " + count + "種擺放方式");
}
static class Location {
    int x;
    int y;
    public Location(int x, int y) {
        this.x = x;
        this.y = y;
    }
    @Override
    public String toString() {
        return "(" + x + "," + y + ")";
    }
}
public static void printResult(LinkedList<Location> arr) {
    if (arr.size() == 0) {
        return;
    }
    System.out.println("第" + (count + 1) + "種:");
    for (int i = 0; i < arr.size(); i++) {
        System.out.print(arr.get(i).toString() + "\t");
    }
    System.out.println();
    count++;
}
public static void traceBack(LinkedList<Location> arr, int x, int y) {
    if (arr.size() == size) {
        printResult(arr);
    }
    for (int i = x; i < size; i++) {
        Location location = new Location(i, y);
        if (isOk(arr, location)) {//判斷是否滿足排列要求秤掌,不滿足回溯到上一層 判斷同行的下一列位置
            arr.offer(location);//保存擺好的皇后
            System.out.println("offer:" + "(" + location.x + ", " + location.y + ")");
            traceBack(arr, 0, y + 1);//開始排下一行的皇后
            arr.pollLast();//當前不滿足條件則取消上一次擺放方案,重新擺放
            System.out.println("polllast:" + "(" + location.x + ", " + location.y + ")");
        }
    }
}
public static boolean isOk(LinkedList<Location> arr, Location oriLocation) {
    for (Location loc : arr) {
        if (loc.x == oriLocation.x || loc.y == oriLocation.y) { //同行同列判斷
            return false;
        } else if (Math.abs(loc.x - oriLocation.x) == Math.abs(loc.y - oriLocation.y)) {//斜對角線判斷
            return false;
        }
    }
    return true;
}
5)剪繩子問題 (貪心與動態(tài)規(guī)劃)

題干:一根長度為n的繩子鹰霍,請把繩子剪成m段机杜,最終每段繩子長度的乘積最大值是多少?例如衅谷,當繩子的長度為8時,我們剪成3,3,2三段似将,最大乘積是18获黔。
動態(tài)規(guī)劃解:

public static int dp(int len) {
    if (len < 2)
        return 0;
    if (len == 2)
        return 1;
    if (len == 3)
        return 2;
    //子問題的最優(yōu)解存儲在arr數(shù)組中,第i個元素表示把長度為i的繩子剪成若干段后各段長度乘積的最大值
    int[] arr = new int[len + 1];
    //這些情況下在验,不剪的時候長度比剪的時候長玷氏,所以作為初始條件
    arr[0] = 0;
    arr[1] = 1;
    arr[2] = 2;
    arr[3] = 3;
    for (int i = 4; i <= len; i++) {
        int max = 0;
        for (int j = 1; j <= i / 2; j++) {
            //動態(tài)規(guī)劃:以上一個子問題的最優(yōu)解為依據(jù)來求下一個子問題的最優(yōu)解
            int num = arr[j] * arr[i - j];
            System.out.println("i:" + i + " arr[" + j + "] * " + "arr[" + (i - j) + "]" + " " + "num:" + num);
            if (max < num)
                max = num;
        }
        arr[i] = max;
    }
    return arr[len];
}

貪心解:

public static int greedy(int len) {
    /**
     * 先找規(guī)律
     * len = 1  1
     *
     * len = 2  1
     * len = 3  2
     *
     * len = 4  2*2 4
     * len = 5  2*3 6
     * len = 6  3*3 9
     * len = 7  3*2*2 12
     * len = 8  3*3*2 18
     * len = 9  3*3*3 27
     * len = 10 3*3*2*2 36
     * ...
     * 從5開始,就由3和2組成腋舌,有3盡量滿足3盏触,如何最后剩余3和1則轉(zhuǎn)為2*2
     * 貪心:有最優(yōu)解3,盡量湊成3块饺,最后3*1 的情況特殊考慮轉(zhuǎn)為2*2
     */
    if (len == 1) {
        return 1;
    }
    if (len > 1 && len < 4) {
        return len - 1;
    }
    if (len == 4) {
        return len;
    }
    if (len % 3 == 1) {
        return (int) Math.pow(3, len / 3 - 1) * (int) Math.pow(2, 2);
    } else {
        return (int) Math.pow(3, len / 3) * 2;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載赞辩,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末授艰,一起剝皮案震驚了整個濱河市辨嗽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌淮腾,老刑警劉巖糟需,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異谷朝,居然都是意外死亡洲押,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門圆凰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來杈帐,“玉大人,你說我怎么就攤上這事送朱∧锏矗” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵驶沼,是天一觀的道長炮沐。 經(jīng)常有香客問我,道長回怜,這世上最難降的妖魔是什么大年? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任换薄,我火速辦了婚禮,結(jié)果婚禮上翔试,老公的妹妹穿的比我還像新娘轻要。我一直安慰自己,他們只是感情好垦缅,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布冲泥。 她就那樣靜靜地躺著,像睡著了一般壁涎。 火紅的嫁衣襯著肌膚如雪凡恍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天怔球,我揣著相機與錄音嚼酝,去河邊找鬼。 笑死竟坛,一個胖子當著我的面吹牛闽巩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播担汤,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼涎跨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了漫试?” 一聲冷哼從身側(cè)響起六敬,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎驾荣,沒想到半個月后外构,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡播掷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年审编,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歧匈。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡垒酬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出件炉,到底是詐尸還是另有隱情勘究,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布斟冕,位于F島的核電站口糕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏磕蛇。R本人自食惡果不足惜景描,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一十办、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧超棺,春花似錦向族、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至氧苍,卻和暖如春适肠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背候引。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留敦跌,地道東北人澄干。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像柠傍,于是被迫代替她去往敵國和親麸俘。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容