android面試筆記總結(算法篇)

Android面試總結(算法篇)

快速排序

  • 每次取一個基準值审孽,然后每次從基準值左邊和右邊取值,找到基準值左邊比基準值大或等于的值,找到基準值右邊比基準值小或等于的值,然后左邊和右邊的值進行交換
  • 完成上面一趟交換后格嗅,基準值左邊的再進行循環(huán)比較番挺,基準值右邊的再循環(huán)比較
/**
 * 快速排序
 *
 * @param arr
 * @param L   指向數(shù)組第一個元素
 * @param R   指向數(shù)組最后一個元素
 */
public static void quickSort(int[] arr, int L, int R) {
    int i = L;
    int j = R;
    //支點以數(shù)組的中間的數(shù)為準
    int pivot = arr[(L + R) / 2];
    //左右兩端進行掃描,只要兩端還沒有交替屯掖,就一直掃描
    while (i <= j) {
        //在左邊找比支點大的數(shù)
        while (pivot > arr[i])
            i++;
        //在右邊找比支點小的數(shù)
        while (pivot < arr[j])
            j--;
        //此時已經(jīng)分別找到了比支點小的數(shù)(右邊)玄柏、比支點大的數(shù)(左邊),它們進行交換
        if (i <= j) {
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
            i++;
            j--;
        }
        for (int m = 0; m < arr.length; m++) {
            System.out.print(" " + arr[m]);
        }
        System.out.println("");
    }
    //上面一個while保證了第一趟排序支點的左邊比支點小贴铜,支點的右邊比支點大了禁荸。
    //“左邊”再做排序,直到左邊剩下一個數(shù)(遞歸出口)
    if (L < j)
        quickSort(arr, L, j);
    //“右邊”再做排序阀湿,直到右邊剩下一個數(shù)(遞歸出口)
    if (i < R)
        quickSort(arr, i, R);
}

插入排序

//插入排序
public void insertSort(int[] array) {
    for (int i = 1; i < array.length; i++) {
        int temp = array[i];//當前的值
        int j = i - 1;//定位到當前索引的前一個
        while (j >= 0 && temp < array[j]) {
            //前面的數(shù)比當前值要大,則將前面的值替換給當前值
            array[j + 1] = array[j];
            //位置向前進一位
            j--;
        }
        //將當前值放到最前面的索引
        array[j + 1] = temp;
    }
}

選擇排序

  • 第一層循環(huán)表示前面的數(shù)瑰妄,后面一層循環(huán)表示后面的數(shù)
  • 而冒泡排序的第一層循環(huán)表示每一輪循環(huán)的次數(shù)
public static void order() {
    int[] a = {3, 0, 1, 2, 11, 7};
    for (int i = 0; i < a.length - 1; i++) {
        for (int j = i; j < a.length; j++) {
            int temp;
            if (a[i] > a[j]) {
                temp = a[j];
                a[j] = a[i];
                a[i] = temp;
            }
        }
    }
    for (int i = 0; i < a.length; i++) {
        System.out.println("result:" + a[i]);
    }
}

冒泡排序

  • 跟選擇排序的不同地方是第一層循環(huán)表示每一輪循環(huán)的次數(shù)
public static void sort() {
    int[] a = {3, 0, 1, 2, 11, 7};
    for (int i = 1; i < a.length; i++) {
        for (int j = 0; j < a.length - i; j++) {
            if (a[j] > a[j + 1]) {
                int temp = a[j + 1];
                a[j + 1] = a[j];
                a[j] = temp;
            }
        }
    }
    for (int i = 0; i < a.length; i++) {
        System.out.println("result:" + a[i]);
    }
}

二分法查找

  • 排序好的數(shù)組陷嘴,找出對應數(shù)的位置,沒找到的話返回-1
//二分法查找
public  int erfenfa(int[] array, int find) {
    int min = 0;
    int max = array.length - 1;
    int result = -1;
    while (min <= max) {
        int temp = (max + min) / 2;
        //如果要找的數(shù)比中間值小间坐,則將最大的索引向左移一位
        //,否則將最小的索引向右移一位
        if (find < array[temp]) {
            max = temp - 1;
        } else if (find > array[temp]) {
            min = temp + 1;
        } else {
            result = temp;
            break;
        }
    }
    return result;
}

兩個棧實現(xiàn)隊列

  • 棧的規(guī)則是先進后出灾挨,后進先出,隊列是先進先出竹宋,后進后出
public class StackQueue {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    public void push(int node){
        //實現(xiàn)隊列的push直接將元素放到第一個棧中
        stack1.push(node);
    }
    public int pop(){
        //如果第2個棧是空的劳澄,需要將第一個棧的數(shù)據(jù)依次取出來
        if(stack2.empty()){
            //直到第一個棧中的數(shù)據(jù)取完了
            while(!stack1.empty())
                stack2.push(stack1.pop());
        }
        return stack2.pop();
    }
}

鏈表常見題

  • 常見題型有鏈表翻轉、求倒數(shù)第k個節(jié)點蜈七、判斷是不是環(huán)形鏈表秒拔、鏈表部分翻轉、鏈表合并飒硅、鏈表排序等砂缩。
  • 鏈表有一個next指向下一個指針,如果next=null說明到了鏈表的結束位置三娩,環(huán)鏈表除外庵芭,后面題型會涉及到環(huán)形鏈表
public static class ListNode {
    int val;
    ListNode next = null;
    ListNode(int val) {
        this.val = val;
    }
}

翻轉鏈表

//鏈表翻轉,思想是定義一個節(jié)點雀监,然后節(jié)點的pre指向了節(jié)點的next
//1->2->3->4->5
//5->4->3->2->1
public  ListNode revertListNode(ListNode listNode) {
    ListNode preNode = null;
    ListNode nextNode;
    while (listNode != null) {
        //先取出next双吆,后面放到listNode的時候用
        nextNode = listNode.next;
        //preNode指向next節(jié)點
        listNode.next = preNode;
        //將當前節(jié)點給到pre,下次判斷節(jié)點的時候用得到
        preNode = listNode;
        listNode = nextNode;
    }
    return preNode;
}

求鏈表中倒數(shù)第k個結點

/**
 * 輸入一個鏈表会前,輸出該鏈表中倒數(shù)第k個結點好乐。
 *
 * @param head
 * @param k
 * @return
 */
public static ListNode FindKthToTail(ListNode head, int k) {
    ListNode second = head;
    ListNode first = head;
    //雙指針的思想,讓第一個指針先走回官,走到第k個結點后曹宴,第二個指針也跟著走,
    // 當?shù)谝粋€節(jié)點走到最后的時候歉提,第二個節(jié)點位置就是倒數(shù)第k個結點的位置
    for (int i = 0; i < k; i++) {
        first = first.next;
    }
    while (first != null) {
        first = first.next;
        second = second.next;
    }
    return second;
}

判斷一個鏈表是否有環(huán)

/**
 * 判斷一個鏈表是不是環(huán)形鏈表
 * 定義個塊的指針和慢的指針笛坦,如果兩個再次相遇說明是環(huán)形鏈表
 * @param head
 * @return
 */
private boolean isLoop(ListNode head) {
    //定義快慢指針
    ListNode fast = head.next;
    ListNode slow = head.next;
    while(fast != null && slow != null && fast.next != null) {
            //快指針每次走兩步区转,慢指針每次走一步
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {
                //如果再次相遇,則說明有環(huán)版扩,返回true
                return true;
            }
        }
    }
    return false;
}

每k位進行翻轉鏈表

  • 每k位翻轉鏈表是在整個鏈表翻轉的基礎上演變而來的废离,它是先將鏈表分成每k個來進行翻轉,然后將當前翻轉的結果給上一次翻轉結果的最后一個指針
public static ListNode reverse(ListNode head, int k) {
    ListNode current = head;
    ListNode next = null;
    ListNode prev = null;
    int count = 0;
     //翻轉的條件
    while (current != null && count < k) {
        next = current.next;
        current.next = prev;
        prev = current;
        current = next;
        count++;
    }
    //如果后面還有元素礁芦,則遞歸翻轉
    if (next != null) {
          //將下一次翻轉的結果給當前最后一個元素的next位置
        head.next = reverse(next, k);
    }
    return prev;
}

二叉樹常見題

  • 二叉樹常見題型有二叉樹深度計算蜻韭、二叉樹的鏡像二叉樹、根據(jù)二叉樹的前序遍歷柿扣、和中序遍歷順序求出二叉樹結構肖方。
  • 二叉樹有一個左子節(jié)點和右子節(jié)點。
public static class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) {
        val = x;
    }
}

求二叉樹的深度

public static int TreeDepth(TreeNode root) {
    //如果當前節(jié)點為空未状,說明已經(jīng)到底了
    if (root == null)
        return 0;
    //遞歸調用深度左右子樹的深度
    int left = TreeDepth(root.left);
    int right = TreeDepth(root.right);
    //取左右子樹大的深度值
    return left > right ? left + 1 : right + 1;//每次將調用次數(shù)加1
}

輸入兩棵二叉樹A俯画,B,判斷B是不是A的子結構

public boolean HasSubtree(TreeNode root1,TreeNode root2) {
 boolean result = false;
    //如果兩個樹都不為空才會走這里
    if (root2 != null && root1 != null) {
        //如果根的值相等
        if (root1.val == root2.val) {
            //找左右子樹是否相等
            result = doesTree1HaveTree2(root1, root2);
        }
        //如果上面分析的結果是不相等司草,繼續(xù)判斷A樹左節(jié)點和B樹或A右節(jié)點和B樹
        if (!result)
            return HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
    }
    return result;
}

public boolean doesTree1HaveTree2(TreeNode node1, TreeNode node2) {
    //如果右邊的樹為空直接說明相等
    if (node2 == null) {
        return true;
    }
    //如果左邊的樹為空直接返回不相等艰垂,說明不包含
    if (node1 == null) {
        return false;
    }
    //如果兩個值也不相等,說明也是不相等的
    if (node1.val != node2.val) {
        return false;
    }
    //繼續(xù)遞歸調用對應的左右子樹
    return doesTree1HaveTree2(node1.left, node2.left) &&
            doesTree1HaveTree2(node1.right, node2.right);
}

求二叉樹的鏡像二叉樹

  • 鏡像二叉樹是將二叉樹在左右方向上旋轉下埋虹,左邊的節(jié)點到右邊猜憎、右邊的節(jié)點到左邊,形如下面:
image.png
  • 思路:左右節(jié)點進行顛倒搔课,然后遞歸調用下一個左胰柑、右子節(jié)點
/**
 * 轉成鏡像二叉樹
 *
 * @param root
 */
public void Mirror(TreeNode root) {
    if (root != null) {
        TreeNode left = root.left;
        TreeNode right = root.right;
        TreeNode temp = left;
        root.left = right;
        root.right = temp;
        Mirror(left);
        Mirror(right);
    }
}

根據(jù)二叉樹的前序遍歷、和中序遍歷順序求出二叉樹結構辣辫。

  • 樹的前序遍歷:先是根節(jié)點旦事、再到左子節(jié)點、再到右子節(jié)點
  • 樹的中序遍歷:先是左子節(jié)點急灭、再到根節(jié)點姐浮、再到右子節(jié)點
    劍指offer上面一道題,已知前序遍歷結果是{1,2,4,7,3,5,6,8}葬馋,中序遍歷結果是{4,7,2,1,5,3,8,6}卖鲤,求該二叉樹的結構。
  • 分析:前序遍歷第一個節(jié)點根節(jié)點畴嘶、然后去中序遍歷里面找根節(jié)點左邊是左子節(jié)點蛋逾、根節(jié)點右邊的都是右子節(jié)點部分,所以我們能確定1是根節(jié)點窗悯,4区匣、7、2是1的左子節(jié)點部分蒋院,5亏钩、3莲绰、8、6是1的右子節(jié)點姑丑,然后在4蛤签、7、2里面繼續(xù)通過前序遍歷的2是首位栅哀,能確定2是左子節(jié)點震肮,4、7是2的左子節(jié)點部分留拾,依次類推戳晌,所以有如下結果:


    image.png
/**
 * pre前序的結果:根左右
 * in后序的結果:左根右
 * pre:{1,2,4,7,3,5,6,8}
 * in:{4,7,2,1,5,3,8,6}
 *
 * @param pre
 * @param in
 * @return
 */
public static TreeNode reConstructBinaryTree(int[] pre, int[] in) {
    TreeNode root = new TreeNode(pre[0]);
    for (int i = 0; i < pre.length; i++) {
        if (pre[0] == in[i]) {
            root.left = reConstructBinaryTree(
                    Arrays.copyOfRange(pre, 1, i + 1), Arrays.copyOfRange(in, 0, i));
            root.right = reConstructBinaryTree(
                    Arrays.copyOfRange(pre, i + 1, pre.length), Arrays.copyOfRange(in, i + 1, in.length));
        }
    }
    return root;
}

找出一個無序數(shù)組中出現(xiàn)超過一半次數(shù)的數(shù)字

/**
 * 計算數(shù)組里面超過一半的數(shù)字,如果沒有這樣的數(shù)字痴柔,則返回0
 * 先把數(shù)組排序躬厌,如果有超過一半的數(shù)字,則中間位置的數(shù)字一定是該數(shù)字
 * 然后通過出現(xiàn)該數(shù)的次數(shù)來判斷是否超過一半
 *
 * @param array
 * @return
 */
public static int MoreThanHalfNum_Solution(int[] array) {
    Arrays.sort(array);
    int temp = array[array.length / 2];
    int num = 0;
    for (int i = 0; i < array.length; i++) {
        if (temp == array[i]) {
            num++;
        }
    }
    if (num <= array.length / 2) {
        temp = 0;
    }
    return temp;
}

在一個二維數(shù)組中(每個一維數(shù)組的長度相同)竞帽,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序鸿捧。請完成一個函數(shù)屹篓,輸入這樣的一個二維數(shù)組和一個整數(shù),判斷數(shù)組中是否含有該整數(shù)匙奴。

public boolean Find(int target, int [][] array) {
    int row=0;
    int column=array[0].length-1;
    while(row<array.length&&column>=0){
        if(array[row][column]==target){
            return true;
        }
        if(array[row][column]>target){
            column--;
        }else{
            row++;
        }
    }
    return false;
}
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末堆巧,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子泼菌,更是在濱河造成了極大的恐慌谍肤,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哗伯,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機盛卡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門新症,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人虐块,你說我怎么就攤上這事俩滥。” “怎么了贺奠?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵霜旧,是天一觀的道長。 經(jīng)常有香客問我儡率,道長挂据,這世上最難降的妖魔是什么以清? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮棱貌,結果婚禮上玖媚,老公的妹妹穿的比我還像新娘。我一直安慰自己婚脱,他們只是感情好今魔,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著障贸,像睡著了一般错森。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上篮洁,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天涩维,我揣著相機與錄音,去河邊找鬼袁波。 笑死瓦阐,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的篷牌。 我是一名探鬼主播睡蟋,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼枷颊!你這毒婦竟也來了戳杀?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤夭苗,失蹤者是張志新(化名)和其女友劉穎信卡,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體题造,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡傍菇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了界赔。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桥嗤。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖仔蝌,靈堂內(nèi)的尸體忽然破棺而出泛领,到底是詐尸還是另有隱情,我是刑警寧澤敛惊,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布渊鞋,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏锡宋。R本人自食惡果不足惜儡湾,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望执俩。 院中可真熱鬧徐钠,春花似錦、人聲如沸役首。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽衡奥。三九已至爹袁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間矮固,已是汗流浹背失息。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留档址,地道東北人盹兢。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像守伸,于是被迫代替她去往敵國和親蛤迎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345