• 面试题随记一


    刚经历某互联网公司第一轮面试,面试题为三道编程题,三十分钟内完成,完成两道,剩余一道由于时间不够所以就写出了思路,在这里做一个记录。具体算法思想见代码注解。

    数组操作,求:交集、并集、差集

    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;
            }
        }
    }
    
    
  • 相关阅读:
    angularjs select
    DataInputStream和DataOutputStream
    Linux gcc编译器
    Linux 网络配置
    Linux 实用工具vi
    Linux 文件系统
    Linux Linux系统管理命令
    Linux Linux常用命令二
    Linux Linux常用命令一
    数据结构 排序(归并排序)
  • 原文地址:https://www.cnblogs.com/mrxiaobai-wen/p/14968534.html
Copyright © 2020-2023  润新知