面試題隨記一

小白先生哦發表於2021-07-04

剛經歷某網際網路公司第一輪面試,面試題為三道程式設計題,三十分鐘內完成,完成兩道,剩餘一道由於時間不夠所以就寫出了思路,在這裡做一個記錄。具體演算法思想見程式碼註解。

陣列操作,求:交集、並集、差集

import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * 陣列操作,求:交集、並集、差集
 *
 * 在能夠表達演算法思想的前提下儘量簡化一下情況,所以這裡就假定陣列內元素不重複
 */
public class ArrayOperation {

    @Test
    public void test() {
        int[] arr1 = new int[]{1,3,6,9,8};
        int[] arr2 = new int[]{1,3,6,11,10};
        // 排序測試
        sort(arr1,0,arr1.length - 1);
        sort(arr2,0,arr2.length - 1);

        // 交集
        List<Integer> intersectionResult = intersection(arr1,arr2);
        // 並集
        List<Integer> unionResult = union(arr1,arr2);
        // 差集
        List<Integer> differenceResult = difference(arr1,arr2);
    }

    /**
     * 快排
     *
     * 思路:挖坑填數+分治法
     */
    private void sort(int[] arr,int low,int high) {
        if (low >= high) {
            return;
        }
        int left = low,right = high;
        int movedVal = arr[left];
        while (left < right) {
            while (left < right && arr[right] >= movedVal) {
                right--;
            }
            arr[left] = arr[right];
            while (left < right && arr[left] <= movedVal) {
                left++;
            }
            arr[right] = arr[left];
        }
        arr[left] = movedVal;
        sort(arr,low,left - 1);
        sort(arr,left + 1,high);
    }

    /**
     * 交集
     *
     * 思路:將兩個有序陣列遍歷,相等則加入結果中,不等較小值的陣列索引加1,直到任意一個陣列遍歷完成
     */
    private List<Integer> intersection(int[] arr1,int[] arr2) {
        sort(arr1,0,arr1.length - 1);
        sort(arr2,0,arr2.length - 1);
        List<Integer> result = new ArrayList<>();
        int index1 = 0,index2 = 0;
        int len1 = arr1.length,len2 = arr2.length;
        while (index1 < len1 && index2 < len2) {
            if (arr1[index1] == arr2[index2]) {
                result.add(arr1[index1]);
                index1++;
                index2++;
            } else if (arr1[index1] > arr2[index2]) {
                index2++;
            } else {
                index1++;
            }
        }
        return result;
    }

    /**
     * 並集
     *
     * 思路:依次遍歷兩個陣列,相等索引資料加入到結果中一次,兩個索引同時加1,不相等的將較小值加入結果同時索引加1;當任意一個陣列遍歷完後,將另一個陣列剩餘元素新增進結果;
     */
    private List<Integer> union(int[] arr1,int[] arr2) {
        int len1 = arr1.length,len2 = arr2.length;
        sort(arr1,0,len1 - 1);
        sort(arr2,0,len2 - 1);
        int index1 = 0,index2 = 0;
        List<Integer> result = new ArrayList<>();
        while (index1 < len1 && index2 < len2) {
            if (arr1[index1] == arr2[index2]) {
                result.add(arr1[index1]);
                index1++;
                index2++;
            } else if (arr1[index1] > arr2[index2]) {
                result.add(arr2[index2]);
                index2++;
            } else {
                result.add(arr1[index1]);
                index1++;
            }
        }
        while (index1 < len1) {
            result.add(arr1[index1]);
            index1++;
        }
        while (index2 < len2) {
            result.add(arr2[index2]);
            index2++;
        }
        return result;
    }

    /**
     * 差集
     *
     * 思路:依次遍歷兩個陣列,值相等索引同時加1忽略相同值;不同值加入較小值並將索引加1,直到任意一個陣列遍歷完成;然後將另一個素組中剩餘元素加進結果中。
     */
    private List<Integer> difference(int[] arr1,int[] arr2) {
        int len1 = arr1.length,len2 = arr2.length;
        int index1 = 0,index2 = 0;
        List<Integer> result = new ArrayList<>();
        while (index1 < len1 && index2 < len2) {
            if (arr1[index1] == arr2[index2]) {
                index1++;
                index2++;
            } else if (arr1[index1] > arr2[index2]) {
                result.add(arr2[index2]);
                index2++;
            } else {
                result.add(arr1[index1]);
                index1++;
            }
        }
        while (index1 < len1) {
            result.add(arr1[index1]);
            index1++;
        }
        while (index2 < len2) {
            result.add(arr2[index2]);
            index2++;
        }
        return result;
    }
}

求一個陣列中的連續子列表的最大和

import org.junit.Test;

/**
 * 求一個陣列中的連續子列表的最大和
 */
public class SubListSum {

    @Test
    public void test() {
        int[] arr = new int[]{1,2,3,6,7,8,5,6};
        // 測試結果 21
        int sum = subListSum(arr);
    }

    /**
     * 思路:使用動態規劃
     * 初始dp[0] = arr[0]
     * 如果arr[i] = arr[i - 1],則dp[i] = dp[i - 1] + arr[i]
     * 否則dp[i] = arr[i]
     */
    private int subListSum(int[] arr) {
        int[] dp = new int[arr.length];
        dp[0] = arr[0];
        int sum = dp[0];
        for (int i = 1;i < arr.length;i++) {
            if (arr[i] == arr[i - 1] + 1) {
                dp[i] = dp[i - 1] + arr[i];
            } else {
                dp[i] = arr[i];
            }
            sum = Math.max(sum,dp[i]);
        }
        return sum;
    }
}

求元素首次出現下標

import java.util.ArrayList;
import java.util.List;

/**
 * 一個可能多次重複元素的陣列,然後找出給定值首次出現的下標,如果未出現返回-1
 */
public class FirstSubscript {

    /**
     * 整體思路:將元素和對應下標組成一對,不斷的插入一個列表中生成一個有序列表,然後查詢的時候使用二分查詢
     *
     * 進階思路:將元素和對應小標組成一對,維護一個紅黑樹,使用紅黑樹進行插入和查詢
     */
    public static void main(String[] args) {
        int[] arr = new int[]{1,1,2,1,2,2,7,8,9,9,8,7};
        FirstSubscript fs = new FirstSubscript(arr);
        // 7首次出現下標 6
        int result1 = fs.queryFirstIndex(7);
        // 20未出現 -1
        int result = fs.queryFirstIndex(20);
    }

    private List<Entry> list = new ArrayList<>();

    public FirstSubscript(int[] arr) {
        for (int i = 0;i < arr.length;i++) {
            int val = arr[i];
            int li = 0;
            while (li < list.size() && list.get(li).val < val) {
                li++;
            }
            if (li >= list.size() || list.get(li).val != val) {
                if (li >= list.size()) {
                    list.add(new Entry(val,i));
                } else {
                    list.set(li,new Entry(val,i));
                }
            }
        }
    }

    /**
     * list進行二分查詢
     */
    private int queryFirstIndex(int val) {
        int left = 0,right = list.size() - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            int tempVal = list.get(mid).val;
            if (tempVal == val) {
                return list.get(mid).index;
            } else if (tempVal > val) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return -1;
    }

    private class Entry {
        int val;
        int index;

        Entry(int val,int index) {
            this.val = val;
            this.index = index;
        }
    }
}

相關文章