top interview questions 1

举例法,模式匹配法,简化推广法,简单构造法,数据结构头脑风暴
很多题目都是需要out of box的想法
递归除了跟动态规划结合,还可以升级成回溯法,回溯法的递归基有时要按照规则进行。

横向纵向数组都有序,查找某个元素

从左下角开始查找
top 每一个题目都有记录

买股票的5个问题

121. Best Time to Buy and Sell Stock

思路: 出现最小更新最小,否则更新最大利润。只进行第一次操作(买和卖)

122. Best Time to Buy and Sell Stock II

不限制操作次数
思路:1.贪心问题,如果后面比前面大,就把差值加上
2.找到波谷波峰,波谷买入,波峰卖出

309. Best Time to Buy and Sell Stock with Cooldown

思路:动态规划,给定三个状态,对值进行确定。画出三个状态以及状态之间的转移图即可得出状态转移方程。这个是简单的一维动态规划。

123. Best Time to Buy and Sell Stock III

要求:给定输入只能有两次交易,得到最大金额,更加泛华的解法看下一题,有k次交易的机会

188. Best Time to Buy and Sell Stock IV

要求:只有k完整交易机会,只有买和卖两种状态,然后构建两个二维数组,第二个二维数组的长度为k+1
ac:trick 1.只有在sell时才是一次完整的交易,
2.初始化时候buy[i][0] 和 buy[0][k] 的赋值,
3.sell[0][k] 的赋值
到此,买股票问题全部解决

171. Excel Sheet Column Number

ac: 本质上是26进制转换问题

链表的几个类似的问题

237. Delete Node in a Linked List

要求:删除一个元素,但是只给你当前元素的结点
ac:将下一个的值赋值给当前的元素,然后删除下一个元素

203. Remove Linked List Elements

错误:只是用一个指针,无法删除形如[1,1],这样的最后一个元素
ac:利用dummy,加上两个指针。

147. Insertion Sort List

要求:实现链表的插入排序,

412. Fizz Buzz整除3,输出Fizz,整除5 ,输出Fuzz,整除3和5输出FizzFuzz

最优解,搞两个参数,每次处理后自动清零

108. Convert Sorted Array to Binary Search Tree

递归解决

454. 4Sum II

4个数组,每个数组取出一个数,只要和为0,就满足需求,输出多少种组合。
最优解: O(n平方),先对AB的和用Map进行缓存,然后对CD和取出,看看能否拼成0

 map.put(sum, map.getOrDefault(sum, 0) + 1);
378. Kth Smallest Element in a Sorted Matrix

行升序,列升序,得到特定序号的值
思路:原来是打算构建完整的优先队列,这个不需要,只是对x + 1进行入队列即可,不

public class Solution {
    public int kthSmallest(int[][] matrix, int k) {
        int n = matrix.length;
        PriorityQueue<Tuple> pq = new PriorityQueue<Tuple>();
        for(int j = 0; j <= n-1; j++) pq.offer(new Tuple(0, j, matrix[0][j]));
        for(int i = 0; i < k-1; i++) {
            Tuple t = pq.poll();
            if(t.x == n-1) continue;
            pq.offer(new Tuple(t.x+1, t.y, matrix[t.x+1][t.y]));
        }
        return pq.poll().val;
    }
}
class Tuple implements Comparable<Tuple> {
    int x, y, val;
    public Tuple (int x, int y, int val) {
        this.x = x;
        this.y = y;
        this.val = val;
    }

    @Override
    public int compareTo (Tuple that) {
        return this.val - that.val;
    }
}
//二分查找,感觉有点不科学,时间复杂度较高
public class Solution {
    public int kthSmallest(int[][] matrix, int k) {
        int lo = matrix[0][0], hi = matrix[matrix.length - 1][matrix[0].length - 1] + 1;//[lo, hi)
        while(lo < hi) {
            int mid = lo + (hi - lo) / 2;
            int count = 0,  j = matrix[0].length - 1;
            for(int i = 0; i < matrix.length; i++) {
                while(j >= 0 && matrix[i][j] > mid) j--;
                count += (j + 1);
            }
            if(count < k) lo = mid + 1;
            else hi = mid;
        }
        return lo;
    }
}// 虽然没有直接进行比较,但是通过count的数值进行了比较,这个二分取得是最左边第一个满足条件的数
22. Generate Parentheses

括号匹配的问题,用递归来实现
根据正反括号的个数进行匹配
不使用StringBuffer反而更快,这个是包装类,传送的是地址。由于String存在的唯一性,内部自己实现复制

230. Kth Smallest Element in a BST

思路:2种时间复杂度低的方法,一个是二叉树的递归遍历,一个是非递归版本中序遍历,
非递归版本的遍历需要注意的是k–,不用新建变量

//递归版本的解法
public class Solution {
    private static int count;
    private static int val;
    public int kthSmallest(TreeNode root, int k) {
        this.count = k;
        helper(root);
        return val;
    }

    public void helper(TreeNode root) {
        if (root.left != null) {
            helper(root.left);
        }
        count--;
        if (count == 0) {
            this.val = root.val;
        }
        if (root.right != null){
            helper(root.right);
        }
    }
}
328. Odd Even Linked List

将链表处于奇数个的位置连起来,然后将处于偶数个的位置连起来,奇数尾部跟着第一个偶数
思路: 两个指针,形同删除,最后连接

287. Find the Duplicate Number

给定n + 1个数, 数的范围为1到n
思路:快行指针,与循环链表的类似,
最优解:对当前数组下标立面的数编程负的

public class Solution {
    public int findDuplicate(int[] nums) {
        if (nums.length > 1) {
            int slow = nums[0];
            int fast = nums[nums[0]];
            while (slow != fast){
                slow = nums[slow];
                fast = nums[nums[fast]];
            }
            fast = 0;
            while (slow != fast) {
                fast = nums[fast];
                slow = nums[slow];
            }
            return slow;
        }
        return -1;
   }
}
46. Permutations

Given a collection of distinct numbers, return all possible permutations.
给出一数组的所有线性排列组合,数组中的数都不重复
思路: 1。回溯法,利用递归实现
2.交换法,交换数组中的数,最后方法列表中去
3.插入法 , 例如只有1 , 加上 2 就是 1, 2;2, 1复制的数比较多,

//回溯法(递归里面的一种)典型的形式,需要在递归后对链表数据进行删除
public class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>>  list = new LinkedList<>();
        List<Integer> templist = new LinkedList<>();
        backTrack(list, templist, nums, 0);
        return list;
    }
    public void backTrack(List<List<Integer>> list, List<Integer> templist, int[] nums, int len) {
        if (len == nums.length) {
            list.add(new LinkedList<Integer>(templist));
            return;
        } else {
            for (int i = 0; i < nums.length; i++) {
                if (templist.contains(nums[i])) {
                    continue;
                }
                templist.add(nums[i]);
                backTrack(list, templist, nums, len + 1);
                templist.remove(templist.size() - 1);
            }
        }
    }
}
//还有一种是交换的方法,这里暂时不是。java不可以直接添加数组
//第三种方法,插入法
public class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> list = new ArrayList<List<Integer>>();
        List<Integer> temp = new ArrayList<Integer>();
        temp.add(nums[0]);
        list.add(temp);
        for (int i = 1; i < nums.length; i++) {
            List<List<Integer>> tempres = new ArrayList<List<Integer>>();
            for (int j = 0; j <= i; j++) {
                for (List<Integer> l : list) {
                    List<Integer> sigl = new ArrayList<Integer>(l);
                    sigl.add(j, nums[i]);
                    tempres.add(sigl);
                }
            }
            list = tempres;
        }
        return list;
    }
}
47. Permutations II Given a collection of numbers that might contain duplicates, return all possible unique permutations.
存在重复元素
 if(used[i] || i > 0 && nums[i] == nums[i-1] && !used[i - 1]) continue;
 78. Subsets 
 90. Subsets II     Given a collection of integers that might contain duplicates, nums, return all possible subsets. 
  if(i > start && nums[i] == nums[i-1]) continue; // skip duplicates//因为先进行过排序操作了
62. Unique Paths

m * n的棋盘,从左上角到右下角,多少种不同的路径,只能向下或者向右。
思路: 1直接公式计算
2。迭代加动态规划,设计一个m*n的数组,在处理时,用上面的点加左面点的路径之和,与爬楼梯相似

public class Solution {
    public int uniquePaths(int m, int n) {
        int[][] arr = new int[m][n];
        for (int i = 0; i < m; i++) {
            arr[i][0] = 1;
        }
        for (int j = 0; j < n; j++) {
            arr[0][j] = 1;
        }
        for (int x = 1; x < m; x++) {
            for (int y = 1; y < n; y++){
                arr[x][y] = arr[x - 1][y] + arr[x][y - 1];
            }
        }
        return arr[m - 1][n - 1];
    }
}
341. Flatten Nested List Iterator

Given a nested list of integers, implement an iterator to flatten it.Each element is either an integer, or a list – whose elements may also be integers or other lists.
思路:给定一个实现类,现在要实现iterator迭代器。hasnext 与 next, 这个地方采用的是stack进行缓存,重点在于hasnext将list转换为integer

380. Insert Delete GetRandom O(1)

设计一个数据结构,实现O(1)时间复杂度的插入元素,删除元素,以及获取其中的随机个数。
ArrayList 与 HashMap的结合

215. Kth Largest Element in an Array

给定无序数组,找到最大的第K个数
思路: 1. 先排序
2. 小顶堆,找到第k个大的数用小顶堆,找到第k个小的数,用大顶堆。
3. 选择排序,快排

300. Longest Increasing Subsequence

这个题目以前刷过这个经典的算法
//temp[i]表示的是组成的长度为i + 1的子序列中的list的最小的数,注意结合二分查找

//最优解
public class Solution {
    public int lengthOfLIS(int[] nums) {
        int[] tails = new int[nums.length];
        int size = 0;
        for (int x : nums) {
            int i = 0, j = size;
            while (i != j) {
                int m = i + (j - i) >> 1;
                if (tails[m] < x)
                    i = m + 1;
                else
                    j = m;
            }
            tails[i] = x;
            if (i == size) ++size;
        }
        return size;
    }
}
48. Rotate Image

思路:1.第一个计算处于第几层,第二个计算first- last,这个是要分两层进行的,还要计算偏移量 从 first 到last,last - first = offset, 一般4 *4可以对照着写出来
2. 如果是顺势针, it will be swap(matrix[i][j], matrix[j][i]), (swap(matrix[i][j], matrix[i][matrix.length-1-j])

75. Sort Colors

3种颜色, 0 ,1 ,2进行桶排序
思路:1.用3个数分别进行缓存,桶排序的基础
2.从左到右, 两个num0与num2进行下标的交换存储

116. Populating Next Right Pointers in Each Node

每个二叉树结点多了一个next结点
思路:1。给一个二叉树,对同一级别的,左边的next为右边结点,广搜的改变,增加设计一个包装类,结点为node跟level。这个是很通用的一个方法,不对树有更多的要求
2. 从上到依次进行操作,先将本节点的left 的下一个调整为 right ,然后将本结点的right的下一个调整为 本节点下一个的left, 本节点等于本节点的下一个。为空则进入左子树,对下一层进行操作。对树形有一点要求。这个速度就快了。

289. Game of Life

康威生命游戏,程序实现规则,需要注意的是不可以直接对原数组进行操作,需要将原数组进行复制。
这个很有微软的hihocode的风格,都是基于规则的实现。

162. Find Peak Element

找到峰值点,峰值点的数比左右两个数都大。
最优解: 二分法处理,根据峰的两侧变化趋势相同,可以唯一确定
二分法也是个大法宝,跟递归类似

public class Solution {
    public int findPeakElement(int[] nums) {
        int low = 0;
        int high = nums.length - 1;
        while (low < high) {
            int mid1 = low + ((high - low) >> 1);
            int mid2 = mid1 + 1;
            if (nums[mid1] < nums[mid2]) {
                low = mid2;
            } else {
                high = mid1;
            }
        }
        return low;
    }
}
11. Container With Most Water

给定一个数组,从左往右是表示y,也就是高度,下标为x也就是宽度的位置
最优解: 从左右两边开始迭代,发现高度高于两者的,就进行更新比较,所以速度会快很多

395. Longest Substring with At Least K Repeating Characters

此题一刷无思路,典型的分治法解决的问题. 在子问题上,先从开始到结束统计出各个字母的个数,然后去得26个子母中出现但是出现次数不到k的,进行左右子串的分解,不包括被分解的点。进行递归,返回最大的值。

public class Solution {
    public int longestSubstring(String s, int k) {
        char[] str = s.toCharArray();
        return helper(str, 0, str.length, k);
    }
    private int helper(char[] str, int start, int end,  int k){
        if (end - start < k) {
            return 0;
        }
        int[] count = new int[26];
        for (int i = start; i < end; i++) {
            int ind = str[i] - 'a';
            count[ind]++;
        }
        for (int x = 0; x < 26; x++) {
            if (count[x] < k && count[x] > 0) {
                for (int y = start; y < end; y++) {
                    if (str[y] == x + 'a') {
                        int left = helper(str, start, y, k);
                        int right = helper(str, y + 1, end, k);
                        return Math.max(left, right);
                    }
                }
            }
        }
        return end - start;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值