面試中遇到的手撕代碼題(一)

1.重建二叉樹

輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。

根據二叉樹的性質:
這裏寫圖片描述

public class Rebuild_Tree {

    public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
        // 從頭開始重建
        TreeNode root = reConstructBinaryTree(pre, 0, pre.length - 1, in, 0,
                in.length - 1);
        return root;
    }

    public TreeNode reConstructBinaryTree(int[] pre, int startPre, int endPre,
            int[] in, int startIn, int endIn) {
        if (startPre > endPre || startIn > endIn)// 表示已經構建好了
            return null;
        TreeNode node = new TreeNode(pre[startPre]);// 前序遍歷第一個就是根節點了
        for (int i = 0; i < in.length; i++) {
            if (pre[startPre] == in[i]) {
                node.left = reConstructBinaryTree(pre, startPre + 1, startPre
                        + i - startIn, in, startIn, i - 1);
                node.right = reConstructBinaryTree(pre, startPre + i - startIn
                        + 1, endPre, in, i + 1, endIn);
            }
        }
        return node;
    }
}

2.旋轉數組的最小數字

需要考慮三種情況:
(1)array[mid] > array[high]:
出現這種情況的array類似[3,4,5,6,0,1,2],此時最小數字一定在mid的右邊。
low = mid + 1
(2)array[mid] == array[high]:
出現這種情況的array類似 [1,0,1,1,1] 或者[1,1,1,0,1],此時最小數字不好判斷在mid左邊還是右邊,這時只好一個一個試 ,high = high - 1
(3)array[mid] < array[high]:
出現這種情況的array類似[2,2,3,4,5,6,6],此時最小數字一定就是array[mid]或者在mid的左
邊。因爲右邊必然都是遞增的。
(4)當剩下兩個數據的時候,那麼最小值就是小的那一個樹。

public class Rotate_Min {

    public static int minNumberInRotateArray(int[] array) {
        if(array.length==1) return array[0];
        int low = 0, high = array.length - 1, mid;
        int min = 0;
        while (low < high) {
            if (low + 1 == high)// 只剩下一個的時候target肯定是最小的哪一個
                min = Math.min(array[low], array[high]);
            mid = (low + high) / 2;
            if (array[mid] > array[high])
                low = mid + 1;
            if (array[mid] < array[high])
                high = mid;// 注意,這裏不是mid-1.
            else {
                high = high - 1;
            }
        }
        return min;
    }
}

3.給一個數組返回最小堆或者最大堆

先來看看數據結構
這裏寫圖片描述

然後大頂堆用數組表示如下:
這裏寫圖片描述

我們用簡單的公式來描述一下堆的定義就是:
大頂堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
小頂堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]

public class Max_Heap {

    public static int[] maxHeap(int[] array) {
        // 1.構建大頂堆
        for (int i = array.length / 2 - 1; i >= 0; i--) {
            // 從第一個非葉子結點從下至上,從右至左調整結構
            adjustHeap(array, i, array.length);
        }
        return array;
    }

    private static void adjustHeap(int[] array, int i, int length) {
        int parent = array[i];
        for (int k = 2 * i + 1; k < length; k = k * 2 + 1) {
            // 2*i+1表示左節點,k = k * 2 + 1表示繼續調整子節點
            if (k + 1 < length && array[k] < array[k + 1])
                k = k + 1;// 找到子節點中更大的節點
            if (array[k] > parent) {
                array[i] = array[k];// 父節點變爲更大的值
                i = k;// 修改i的值,使之成爲新的要調整的父節點
            } else {
                break;// 表示無需調整,因爲是自底向上的
            }
        }
        array[i] = parent;// 將temp值放到最終的位置
    }

    public static void main(String[] args) {
        int[] array = { 4, 6, 8, 5, 9 };
        int[] maxHeap = maxHeap(array);
        for (int i : maxHeap) {
            System.out.print(i + " ");
        }
    }
}

那麼手寫堆排序你會不會?

public static void sort(int []arr){
        //1.構建大頂堆
        for(int i=arr.length/2-1;i>=0;i--){
            adjustHeap(arr,i,arr.length);
        }
        //2.調整堆結構+交換堆頂元素與末尾元素
        for(int j=arr.length-1;j>0;j--){
            swap(arr,0,j);//將堆頂元素與末尾元素進行交換
            adjustHeap(arr,0,j);//重新對堆進行調整
        }

    }

4.最大公約數非遞歸算法

求a、b兩個數的最大公約數。

if(a < b){
        temp = a;
        a = b;
        b = temp;

    }
    while(a%b != 0){
            temp = a%b;
            a = b;
            b = temp;
    }
    return b;

5.二維平面有n個點,求一條直線,使最多的點落在該直線上

可以根據A點跟其他點所構成線段的斜率判斷與A點共線的點的個數.遍歷所有點,取出最大值即可,
1.考慮重複點的情況.
2.考慮斜率爲無窮大的情況.

import java.util.HashMap;

//定義座標點

class Point {
    int x;
    int y;
    Point() { x = 0; y = 0; }
    Point(int a, int b) { x = a; y = b; }
}

public class Solution {
//判斷座標點集是否爲空
    public int maxPoints(Point[] points) {
        if(points==null||points.length==0){
            return 0;
        }
//建立Hash表
        HashMap<Double,Integer> map= new HashMap<Double,Integer>();
        int max=1;
        for(int i=0;i<points.length;i++){
            map.clear();       //每次重設A點時,清空Hash表
            map.put((double)Integer.MIN_VALUE,1);//斜率—點數
            int dup=0;
            for(int j=i+1;j<points.length;j++){
            //判斷點是否重合
                if(points[j].x==points[i].x&&points[j].y==points[i].y){
                    dup++;
                    continue;
                }
            //判斷斜率的K值.
                double key=points[j].x-points[i].x==0?
                        Integer.MAX_VALUE:
                            0.0+(double)(points[j].y-points[i].y)/(double)(points[j].x-points[i].x);
                if(map.containsKey(key)){
                    map.put(key,map.get(key)+1);
                }else{
                    map.put(key, 2);
                }
            }
            for(int temp:map.values()){
                if(temp+dup>max){
                    max=temp+dup;
                }
            }
        }
        return max;
    }
}

6.兩數之和

題目的意思:給定任意一個數組,和一個固定值,要求你在數組中找出滿足a+b = target的情況,並返回這兩個值的索引。

Example:

Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
比較簡單,我們只需要藉助一個HashMap即可
其中key=target-nums[i],value=數組的下標

import java.util.HashMap;
import java.util.Map;
public class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int[] result = new int[2];
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        for (int i = 0; i < numbers.length; i++) {
            if(map.containsKey(numbers[i])){
                result[0] = map.get(numbers[i])+1;
                result[1] = i+1;
            }else {
                map.put(target-numbers[i], i);
            }
        }
        return result;
    }
}

7.三個數之和

這裏我們可以借鑑兩數之和的思想,將三數之和看成兩之和與一個target。

public class Three_Sum {

    public static Set<ArrayList<Integer>> threeSum(int[] num) {
        Arrays.sort(num);
        Set<ArrayList<Integer>> result = new HashSet<>();
        for (int i = 0; i < num.length; i++) {
            //target = target-num[i]
            twoSum(num, i, target - num[i], result);
        }
        return result;
    }
    //兩數之和的方法
    public static void twoSum(int[] numbers, int start,
            int target, Set<ArrayList<Integer>> result) {
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        for (int i = start + 1; i < numbers.length; i++) {
            if (map.containsKey(numbers[i])) {
                ArrayList<Integer> round = new ArrayList<Integer>();
                round.add(numbers[start]);
                round.add(numbers[map.get(numbers[i])]);
                round.add(numbers[i]);
                result.add(round);
            }
            map.put(target-numbers[i], i);
        }
    }

    public static void main(String[] args) {
        int[] nums = {-1,0,1,2,-1,-4};
        Set<ArrayList<Integer>> threeSum = threeSum(nums);
        for (ArrayList<Integer> arrayList : threeSum) {
            for (Integer integer : arrayList) {
                System.out.print(integer+",");
            }
            System.out.println();
        }
    }
}

ps:第一部分先寫到這裏

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章