Android面試算法篇(java)


Q:怎么理解數據結構?

  • 技術點:數據結構
  • 思路:數據結構的定義、分類
  • 參考回答:研究數據的邏輯結構和物理結構以及它們之間相互關系,並對這種結構定義相應的運算,而且確保經過這些運算后所得到的新結構仍然是原來的結構類型。
    • 按照邏輯結構分類
      • 線性結構:線性表、棧、隊列
      • 非線性結構:樹、圖
    • 按照存儲結構分為順序結構、鏈式結構、索引結構、哈希結構
 
Q:什么是斐波拉契數列?
  • 技術點:遞歸和循環
  • 思路:斐波那契數列的定義
  • 參考回答:斐波那契數列指的是這樣的數列1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...即這個數列從第3項開始,每一項都等於前兩項之和,數學表示F(1)=1,F(2)=1, F(3)=2,F(n)=F(n-1)+F(n-2)(n>=4,n∈N*)
Q:迭代和遞歸的特點,並比較優缺點
  • 技術點:遞歸和循環
  • 參考回答:遞歸和迭代都是循環的一種,特點:
    • 遞歸就是通過重復調用函數自身實現循環;滿足終止條件時會逐層返回來結束循環
    • 迭代通過函數內某段代碼實現循環;使用計數器結束循環

 

Q:了解哪些查找算法,時間復雜度都是多少?

 

Q:了解哪些排序算法,並比較一下,以及使用場景

 

 Q:二叉排序樹插入或刪除一個節點的過程是怎樣的?

  • 技術點:查找
  • 參考回答:
    • 二叉排序樹插入操作:先查找該元素是否存在於二叉排列樹中並記錄其根節點,若沒有則比較其和根節點大小后插入相應位置
    • 二叉排序樹刪除操作:
      • 待刪除節點是葉子節點,直接刪除即可
      • 待刪除節點是僅有左或右子樹的節點 ,上移子樹即可
      • 待刪除節點是左右子樹都有的節點 ,用刪除節點的直接前驅或直接后繼來替換當前節點

 

Q:什么是紅黑樹?

  • 技術點:查找
  • 參考回答:紅黑樹是一種自平衡二叉查找樹,包含性質:
    • 節點是紅色或黑色
    • 根節點是黑色
    • 葉子節點是黑色
    • 每個紅色節點的兩個子節點都是黑色
    • 從任一節點到其每個葉子的所有路徑都包含相同數目的黑色節點。

 

Q:100盞燈問題

  • 題目描述:問題描述:有100盞燈,編號依次為1,2,3.100,電燈全部關着。現在來了100個人,第一個人把所有的燈開關按下;第二個人隔一個燈按下(2,4,6…);第三個人每隔兩個燈按下(3,6,9…).第100個人隔99個燈按下(100),最后還有幾盞燈,那幾盞燈亮着? 
  • 問題分析:

    對於每個人在拉關開關就是將原來的變反。

    現在第一個人走后,所有的燈全亮;

    第二個人走后,2 的倍數的滅。。。。

    以此類推。。。。。

    • 對於每盞燈,拉動的次數是奇數時,燈就是亮着的,拉動的次數是偶數時,燈就是關着的。
    • 每盞燈拉動的次數與它的編號所含約數的個數有關,它的編號有幾個約數,這盞燈就被拉動幾次。
    • 1~100這100個數中有哪幾個數,約數的個數是奇數。我們知道一個數的約數都是成對出現的,只有完全平方數約數的個數才是奇數個。
所以這100盞燈中有10盞燈是亮着的。
它們的編號分別是: 1、4、9、16、25、36、49、64、81、100。
代碼:
import java.util.*;

public class test{
    private static int count = 0;
    public static void main(String[] args) {
        int a[] = new int[100]; //100盞燈的狀態
        Arrays.fill(a, 0);
        for (int i = 1; i <= a.length; i++){    //100個人
            for (int j = 0; j < a.length; j++){    //100盞燈
                if ((j+1) % i == 0){ //第(j+1)盞燈對於被第i個人的行為后的狀態。
                    if (a[j] == 0){    //原來的狀態取反
                        a[j] = 1;
                    }else{
                        a[j] = 0;
                    }
                }
            }
        }
        for (int c : a){
            if (c == 1){
                count ++;
            }
        }
        System.out.println(count);
    }
}

 

Q:海量數據問題
  • 技術點:海量數據問題
  • 思路:分治、哈希、bit、堆
 
Q:二分查找(手寫)
public static int binarySearch(int[] a, int key){
    int low, mid, high;
    low = 0;
    high = a.length - 1; //最大下標
    while (low <= high){
        mid = (high + low) / 2; //折半下標
        if (key > a[mid]){
            low = mid + 1;    //關鍵字比折半值大,則最小下標調成折半下標的下一位
        }else if (key < a[mid]){
            high = mid - 1;    //關鍵字比折半值小,則最大下標調成折半下標的前一位
        }else{
            return mid;
        }
    }
    return -1;
}

 

Q:反轉鏈表(手寫)
  • 技術點:鏈表
  • 思路:
    • 方法1:重復將首節點的下一個節點調整到最前面,如鏈表1->2->3->4,調整過程為2->1->3->4,3->2->1->4,4->3->2->1
    • 方法2:遞歸,使鏈表從尾節點開始指向前一個節點
  • 參考代碼:
//節點類
public class ListNode{
    int val;
    ListNode next = null;
    ListNode(int val){
        this.val = val;
    }
}

//方法1
public ListNode reverseLinkedList(ListNode head){
    if (head == null || head.next == null){
        return head;
    }
    ListNode p = new ListNode(-1);  //擬1個頭節點
    p.next = head;
    ListNode nextNode = head.next;
    while (nextNode != null){
        //后一個節點調整到最前
        head.next = nextNode.next;
        nextNode.next = p.next;
        p.next = nextNode;
        nextNode = head.next;
    }
    return p.next;
}

//方法2,遞歸
public ListNode reverseLinkedList(ListNode head){
    if (head == null || head.next == null){
        return head;
    }
    ListNode pNode = reverseLinkedList(head.next);
    head.next.next = head;
    head.next = null;
    return pNode;
}

 

Q:用兩個棧實現一個隊列,完成隊列的Push和Pop操作。 隊列中的元素為int類型。(手寫)
  • 技術點:棧和隊列
  • 思路:
    • 入隊:將元素進棧A
    • 出隊:判斷棧B是否為空,如果為空,則將棧A中所有元素pop,並push進棧B,棧B出棧, 反之棧B直接出棧


       
       
  • 參考代碼:
public class Solution{
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    //入隊
    public void add(int node){
        stack1.push(node);
    }
    //出隊
    public int poll(){
        if (stack1.empty(0 && stack2.empty())){
            throw new RuntimeException("Queue is empty!");
        }
        if (stack2.empty()){
            while (!stack1.empty()){
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }
}

 

Q:用三個線程,順序打印字母A~Z,輸出結果是1A,2B,3C,1D,2E。。。
  • 技術點:線程同步
  • 思路:加鎖進行限制,並配合wait()和notifyAll()
  • 參考代碼:
private static char c = 'A';
private static int i = 0;
public static void main(String[] args) {
    Runnable runnable = new Runnable(){
        public void run(){
            synchronized(this){    //加鎖
                try{
                    int threadId = Integer.parseInt(Thread.currentThread().getName());
                    while (i < 26){
                        if (i % 3 == threadId - 1){
                             System.out.println(threadId +""+ (char) c++);
                             i++;
                             notifyAll();// 喚醒處於等待狀態的線程
                        }else{
                            wait(); //釋放當前鎖並進入等待狀態
                        }
                    }
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }//執行結束釋放當前鎖
        }
    };
    Thread t1 = new Thread(runnable, "1");
    Thread t2 = new Thread(runnable, "2");
    Thread t3 = new Thread(runnable, "3");
    t1.start();
    t2.start();
    t3.start();
}

 

 

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM