算法知识点

编程题收集

No3.数组中重复的数字。n个数,范围0到n-1,找到任意一个重复的,时间复杂度O(1);

No4,二维数组查找,从左到右递增,从上到下递增。

No5,字符串空格替换,如果有空格,就将他替换成%20

No6,从尾到头打印链表,递归和非递归方法

No7 重建二叉树,前序遍历和中序遍历重构二叉树

No8 二叉树的下一个节点。中序遍历的二叉树下一个节点,这个树的节点,有指向父指针;

No9,两个栈实现队列

No 10-1,青蛙可以挑一阶,也可以2阶,跳到n阶,几种做法

No10-2,变态跳,可以跳1-n阶,随便跳。求n阶几种方法;

No11,旋转数组最小的数字:非减排序的数组,可能存在重复

No12,矩阵中的路径。矩阵有字符,可以从任意开始,上下左右任意走,但不能走走过的格子,求是否存在一条包含给定字符串的路径。

No13,机器人的运动范围,从(0,0)开始,上下左右移动,但不能进入行坐标和列坐标数位之和大于k的格子,给定k,能打几个格子。

No14,剪绳子,长为n,剪m段(m,n都是整数,且m>1),所有的长度的乘积最大为多少

No15,二进制中1的个数;

No16, 数值的整数次方

No17, 打印从1到最大的n位数

No18-1,删除节点。给定一链表头结点和指定节点,O(1)时间内,删除指定节点

No18-2.删除重复的节点。存在的重复节点,全都删了。

No19,实现函数来匹配包含‘.’和‘*’的正则表达式.

No20实现一个函数来判断字符串是否表示数值。

No20-2将字符串转换成整数;不合法返回0;

No21,调整数组顺序使得奇数位于偶数之前。

No22,返回链表的倒数第k个节点。

No23,链表中环的入口节点;

No24,反转链表,并返回反转之后的头结点。

No25,合并两个有序的链表,重建一个新的,包含所有的两个链表。—>单调不减

No26,输入A和B两个树,判断B是A的子树。空树不是子树

No27,二叉树的镜像。输入一个二叉树,将他变成他的镜像

No28,输入一个二叉树,判断二叉树是不是对称的。

No29,顺时针打印矩阵。

No30,包含min函数的栈

No31,栈的压入弹出序列,第一个表示压入序列,判断第二个是不 是弹出序列。

No32,从上到下打印二叉树

No33,输入一个整数数组,判断是不是二叉搜索树的后序遍历序列

No34,二叉树中和未某一值得路径

No35复杂链表的复制;链表不仅有val,next,还有一个指向任意节点random

No36二叉搜索树和双向链表;二叉搜索树转换成一个排序的双向链表,不能创建新的节点,只能调整指针顺序。

No37实现函数序列化二叉树和反序列二叉树

No38输入一个字符串,给出所有的排列;

No39,数组中出现超过一半的数字,如果不存在,返回0;

No40,最小的k个数

No41,数据流中的中位数,奇数个,中间那个。偶数个,中间俩的平均.

No42,连续子数组的最大和,数组中有正数有负数,求所有连续子数组的最大和。

No43,1-n所有数中,求所有十进制位出现1个总数

No44,从0-n,所有的从前到后排到一块,实现一个函数,求第k位的数字是几?

No45,给定一个数组,求组合到一块的最小数字

No46,0-25翻译成a-z,给一个数字,求有几种翻译方法

No47,礼物的最大价值,矩阵,每一步都有一个值,从左上到右下,只能向右或向下移动,求最大和

No48,最长不含重复字符的子字符串

No49,只含2,3,5因子的数是丑数,1也是,求第n个丑数

No50,第一个只出现一次的字符,返回的是位置

No51,数组中的逆序对,归并排序!!!

No52,两个链表的第一个公共节点。

No53,在排序数组中查找数组,一个数字出现了多少次

No54,二叉搜索树中,第K小节点

No55-1,二叉树深度

No55-2,是不是平衡二叉树

No56-1,一个数组,一个出现一次,其他出现两次,求一次的。

No56-2,数组,一个出现一次,其他出现三次。求一次

No57-1,递增排序的数组,和target.找出一对和为target的数字

No57-2,正数s,给出连续正数序列,其和未s.所有的序列。序列最少有俩。

No58-1,翻转单词顺序

No58-2,左旋转字符串

No59-1给出数组和窗口大小,求滑动窗口的最大值。

No59-2,实现带有max函数的队列,出入队和max都是O(1)

No60,n个色子,点数和为s,s所有可能出现的值得概率

No61,扑克牌抽5个数,是不是顺子。大小王可以为任何;

No62,0到n-1,围一圈,从0开始,删除第m个数字。求最后的数字;

No63,数组,值为股票当时的价格,求最大利润

No65,不用加减乘除做加法

No66,构建乘积数组。

1. 出现频率最多的 k 个元素

Given [1,1,1,2,2,3] and k = 2, return [1,2].
Copy to clipboardErrorCopied
设置若干个桶,每个桶存储出现频率相同的数。桶的下标表示数出现的频率,即第 i 个桶中存储的数出现的频率为 i。
把数都放到桶之后,从后向前遍历桶,最先得到的 k 个数就是出现频率最多的的 k 个数。

//基于桶排序求解「前 K 个高频元素」
class Solution {
    public List<Integer> topKFrequent(int[] nums, int k) {
        List<Integer> res = new ArrayList();
        // 使用字典,统计每个元素出现的次数,元素为键,元素出现的次数为值
        HashMap<Integer,Integer> map = new HashMap();
        for(int num : nums){
            if (map.containsKey(num)) {
               map.put(num, map.get(num) + 1);
             } else {
                map.put(num, 1);
             }
        }
        
        //桶排序
        //将频率作为数组下标,对于出现频率不同的数字集合,存入对应的数组下标
        List<Integer>[] list = new List[nums.length+1];
        for(int key : map.keySet()){
            // 获取出现的次数作为下标
            int i = map.get(key);
            if(list[i] == null){
               list[i] = new ArrayList();
            } 
            list[i].add(key);
        }
        
        // 倒序遍历数组获取出现顺序从大到小的排列
        for(int i = list.length - 1;i >= 0 && res.size() < k;i--){
            if(list[i] == null) continue;
            res.addAll(list[i]);
        }
        return res;
    }
}

8. 修改一个数成为非递减数组

Input: [4,2,3]
Output: True
Explanation: You could modify the first 4 to 1 to get a non-decreasing array.
Copy to clipboardErrorCopied
题目描述:判断一个数组是否能只修改一个数就成为非递减数组。

在出现 nums[i] < nums[i - 1] 时,需要考虑的是应该修改数组的哪个数,使得本次修改能使 i 之前的数组成为非递减数组,并且 不影响后续的操作 。优先考虑令 nums[i - 1] = nums[i],因为如果修改 nums[i] = nums[i - 1] 的话,那么 nums[i] 这个数会变大,就有可能比 nums[i + 1] 大,从而影响了后续操作。还有一个比较特别的情况就是 nums[i] < nums[i - 2],修改 nums[i - 1] = nums[i] 不能使数组成为非递减数组,只能修改 nums[i] = nums[i - 1]。

public boolean checkPossibility(int[] nums) {
    int cnt = 0;
    for (int i = 1; i < nums.length && cnt < 2; i++) {
        if (nums[i] >= nums[i - 1]) {
            continue;
        }
        cnt++;
        if (i - 2 >= 0 && nums[i - 2] > nums[i]) {
            nums[i] = nums[i - 1];
        } else {
            nums[i - 1] = nums[i];
        }
    }
    return cnt <= 1;
}


分析:
一,当数组长度小于3时,最多需要调整一次就能满足条件
二,当数组长度大于等于3时,出现前一个元素y大于后一个元素z时,
如果y的前元素x不存在,让y=z即可;若x存在,会有以下情况

x y z
1 3 2
2 3 1
3 3 1
2 3 2
要满足条件,需要如下调整:
1,当x<z,让y=z
2,当x>z,让z=y
3, 当x=z,让y=z
综合以上可以得到:当x存在且x>z,就让z=y,否则让y=z
当变更超过2次就不再满足条件

class Solution {
    public boolean checkPossibility(int[] nums) {
        if(nums.length < 3){
            return true;
        }
        int count = 0;
        for(int i=0;i<nums.length-1;i++){
            if(nums[i] > nums[i+1]){
                count++;
                if(count > 1){
                    break;
                }
                if(i-1 >=0&&nums[i-1] > nums[i+1]){
                    nums[i+1] = nums[i];
                }else{
                    nums[i] = nums[i+1];
                }
            }
        }
        return count <= 1;
    }
}

1. 分割整数的最大乘积

  1. Integer Break (Medim)

题目描述:For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 + 3 + 4).

class Solution {
    public int integerBreak(int n) {
        if(n <= 3) return n - 1;
        int a = n / 3, b = n % 3;
        if(b == 0) return (int)Math.pow(3, a);
        if(b == 1) return (int)Math.pow(3, a - 1) * 4;
        return (int)Math.pow(3, a) * 2;
    }
}
  1. 最长摆动子序列
  2. Wiggle Subsequence (Medium)
    算法

为了更好地理解这一方法,用两个数组来 dp ,分别记作 upup 和 downdown 。

每当我们选择一个元素作为摆动序列的一部分时,这个元素要么是上升的,要么是下降的,这取决于前一个元素的大小。

up[i]up[i] 存的是目前为止最长的以第 ii 个元素结尾的上升摆动序列的长度。

类似的, down[i]down[i] 记录的是目前为止最长的以第 ii 个元素结尾的下降摆动序列的长度。

我们每当找到将第 ii 个元素作为上升摆动序列的尾部的时候就更新 up[i]up[i] 。现在我们考虑如何更新 up[i]up[i] ,我们需要考虑前面所有的降序结尾摆动序列,也就是找到 down[j]down[j] ,满足 j < ij<i 且 nums[i] >nums[j]nums[i]>nums[j] 。类似的, down[i]down[i] 也会被更新。

public class Solution {
    public int wiggleMaxLength(int[] nums) {
        if (nums.length < 2)
            return nums.length;
        int[] up = new int[nums.length];
        int[] down = new int[nums.length];
        for (int i = 1; i < nums.length; i++) {
            for(int j = 0; j < i; j++) {
                if (nums[i] > nums[j]) {
                    up[i] = Math.max(up[i],down[j] + 1);
                } else if (nums[i] < nums[j]) {
                    down[i] = Math.max(down[i],up[j] + 1);
                }
            }
        }
        return 1 + Math.max(down[nums.length - 1], up[nums.length - 1]);
    }
}


股票交易

1. 需要冷却期的股票交易

  1. Best Time to Buy and Sell Stock with Cooldown(Medium)

题目描述:交易之后需要有一天的冷却时间。

public class Solution {

    public int maxProfit(int[] prices) {
        int len = prices.length;
        // 特判
        if (len < 2) {
            return 0;
        }

        int[][] dp = new int[len][3];

        // 初始化
        dp[0][0] = 0;
        dp[0][1] = -prices[0];
        dp[0][2] = 0;

        for (int i = 1; i < len; i++) {
            dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][2] - prices[i]);
            dp[i][2] = dp[i - 1][0];
        }
        return Math.max(dp[len - 1][0], dp[len - 1][2]);
    }
}

3. 只能进行两次的股票交易

  1. Best Time to Buy and Sell Stock III (Hard)
public class Solution {

    public int maxProfit(int[] prices) {
        int len = prices.length;
        if (len < 2) {
            return 0;
        }

        // dp[i][j] ,表示 [0, i] 区间里,状态为 j 的最大收益
        // j = 0:什么都不操作
        // j = 1:第 1 次买入一支股票
        // j = 2:第 1 次卖出一支股票
        // j = 3:第 2 次买入一支股票
        // j = 4:第 2 次卖出一支股票

        // 初始化
        int[][] dp = new int[len][5];
        dp[0][0] = 0;
        dp[0][1] = -prices[0];

        // 3 状态都还没有发生,因此应该赋值为一个不可能的数
        for (int i = 0; i < len; i++) {
            dp[i][3] = Integer.MIN_VALUE;
        }

        // 状态转移只有 2 种情况:
        // 情况 1:什么都不做
        // 情况 2:由上一个状态转移过来
        for (int i = 1; i < len; i++) {
            // j = 0 的值永远是 0
            dp[i][0] = 0;
            dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
            dp[i][2] = Math.max(dp[i - 1][2], dp[i - 1][1] + prices[i]);
            dp[i][3] = Math.max(dp[i - 1][3], dp[i - 1][2] - prices[i]);
            dp[i][4] = Math.max(dp[i - 1][4], dp[i - 1][3] + prices[i]);
        }
        // 最大值只发生在不持股的时候,因此来源有 3 个:j = 0 ,j = 2, j = 4
        return Math.max(0, Math.max(dp[len - 1][2], dp[len - 1][4]));
    }
}

2. 需要交易费用的股票交易

  1. Best Time to Buy and Sell Stock with Transaction Fee (Medium)
public class Solution {

    public int maxProfit(int[] prices, int fee) {
        int len = prices.length;
        if (len < 2) {
            return 0;
        }

        // dp[i][j] 表示 [0, i] 区间内,到第 i 天(从 0 开始)状态为 j 时的最大收益'
        // j = 0 表示不持股,j = 1 表示持股
        // 并且规定在买入股票的时候,扣除手续费
        int[][] dp = new int[len][2];

        dp[0][0] = 0;
        dp[0][1] = -prices[0] - fee;

        for (int i = 1; i < len; i++) {
            dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i] - fee);
        }
        return dp[len - 1][0];
    }
}

3. 26 进制

public String convertToTitle(int n) {
    StringBuilder sb = new StringBuilder();
    while (n > 0) {
        int c = n % 26;
        if(c == 0){
			c = 26;
			n -= 1;
		}
        sb.insert(0, (char) ('A' + c - 1));
        n /= 26;
    }
    return sb.toString();
}

2. 矩阵的总路径数

矩阵的总路径数
62. Unique Paths (Medium)

题目描述:统计从矩阵左上角到右下角的路径总数,每次只能向右或者向下移动。

思路二:动态规划

我们令 dp[i][j] 是到达 i, j 最多路径

动态方程:dp[i][j] = dp[i-1][j] + dp[i][j-1]

注意,对于第一行 dp[0][j],或者第一列 dp[i][0],由于都是在边界,所以只能为 1

时间复杂度:O(m*n)O(m∗n)

空间复杂度:O(m * n)O(m∗n)

优化:因为我们每次只需要 dp[i-1][j],dp[i][j-1]

所以我们只要记录这两个数,直接看代码吧!

代码
思路二:

class Solution {
    public int uniquePaths(int m, int n) {
        int[][] dp = new int[m][n];
        for (int i = 0; i < n; i++) dp[0][i] = 1;
        for (int i = 0; i < m; i++) dp[i][0] = 1;
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m - 1][n - 1];  
    }
}

1. 统计阶乘尾部有多少个 0

  1. Factorial Trailing Zeroes (Easy)

尾部的 0 由 2 * 5 得来,2 的数量明显多于 5 的数量,因此只要统计有多少个 5 即可。

对于一个数 N,它所包含 5 的个数为:N/5 + N/52 + N/53 + …,其中 N/5 表示不大于 N 的数中 5 的倍数贡献一个 5,N/52 表示不大于 N 的数中 52 的倍数再贡献一个 5 …。

public int trailingZeroes(int n) {
    int count = 0;
    for (int i = 1; i <= n; i++) {
        int N = i;
        while (N > 0) {
            if (N % 5 == 0) {
                count++;
                N /= 5;
            } else {
                break;
            }
        }
    }
    return count;

}

面试算法题记录

1、数组的逆序数

题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

解题思路

private long cnt = 0;
private int[] tmp;  // 在这里声明辅助数组,而不是在 merge() 递归函数中声明

public int InversePairs(int[] nums) {
    tmp = new int[nums.length];
    mergeSort(nums, 0, nums.length - 1);
    return (int) (cnt % 1000000007);
}

private void mergeSort(int[] nums, int l, int h) {
    if (h - l < 1)
        return;
    int m = l + (h - l) / 2;
    mergeSort(nums, l, m);
    mergeSort(nums, m + 1, h);
    merge(nums, l, m, h);
}

private void merge(int[] nums, int l, int m, int h) {
    int i = l, j = m + 1, k = l;
    while (i <= m || j <= h) {
        if (i > m)
            tmp[k] = nums[j++];
        else if (j > h)
            tmp[k] = nums[i++];
        else if (nums[i] <= nums[j])
            tmp[k] = nums[i++];
        else {
            tmp[k] = nums[j++];
            this.cnt += m - i + 1;  // nums[i] > nums[j],说明 nums[i...mid] 都大于 nums[j]
        }
        k++;
    }
    for (k = l; k <= h; k++)
        nums[k] = tmp[k];
}

2、LRU //hashMap加双向链表,双向链表有头尾节点,

Node

class Node {
    public int key, val;
    public Node next, prev;
    public Node(int k, int v) {
        this.key = k;
        this.val = v;
    }
}

DoubleList

class DoubleList {  
    private Node head, tail; // 头尾虚节点
    private int size; // 链表元素数

    //构造函数,new的时候创建一个只有头节点和尾节点的双向队列(头尾都是虚拟节点)
    public DoubleList() {
        head = new Node(0, 0);
        tail = new Node(0, 0);
        head.next = tail;
        tail.prev = head;
        size = 0;
    }

    // 在链表头部添加节点 x
    public void addFirst(Node x) {
        x.next = head.next;
        x.prev = head;
        head.next.prev = x;
        head.next = x;
        size++;
    }

    // 删除链表中的 x 节点(x 一定存在)
    public void remove(Node x) {
        x.prev.next = x.next;
        x.next.prev = x.prev;
        size--;
    }
    
    // 删除链表中最后一个节点,并返回该节点
    public Node removeLast() {
        if (tail.prev == head)
            return null;
        Node last = tail.prev;
        remove(last);
        return last;
    }
    
    // 返回链表长度
    public int size() { return size; }
}

LRUCache思路

// key 映射到 Node(key, val)
HashMap<Integer, Node> map;
// Node(k1, v1) <-> Node(k2, v2)...
DoubleList cache;

int get(int key) {
    if (key 不存在) {
        return -1;
    } else {        
        将数据 (key, val) 提到开头;
        return val;
    }
}

void put(int key, int val) {
    Node x = new Node(key, val);
    if (key 已存在) {
        把旧的数据删除;
        将新节点 x 插入到开头;
    } else {
        if (cache 已满) {
            删除链表的最后一个数据腾位置;
            删除 map 中映射到该数据的键;
        } 
        将新节点 x 插入到开头;
        map 中新建 key 对新节点 x 的映射;
    }
}


```java
class LRUCache {
    // key -> Node(key, val)
    private HashMap<Integer, Node> map;
    // Node(k1, v1) <-> Node(k2, v2)...
    private DoubleList cache;
    // 最大容量
    private int cap;
    
    public LRUCache(int capacity) {
        this.cap = capacity;
        map = new HashMap<>();
        cache = new DoubleList();
    }
    
    public int get(int key) {
        if (!map.containsKey(key))
            return -1;
        int val = map.get(key).val;
        // 利用 put 方法把该数据提前
        put(key, val);
        return val;
    }
    
    public void put(int key, int val) {
        // 先把新节点 x 做出来
        Node x = new Node(key, val);
        
        if (map.containsKey(key)) {
            // 删除旧的节点,新的插到头部
            cache.remove(map.get(key));
            cache.addFirst(x);
            // 更新 map 中对应的数据
            map.put(key, x);
        } else {
            if (cap == cache.size()) {
                // 删除链表最后一个数据
                Node last = cache.removeLast();
                map.remove(last.key);
            }
            // 直接添加到头部
            cache.addFirst(x);
            map.put(key, x);
        }
    }
}

3、最长回文序列 leetocde 5

public String longestPalindrome(String s) {
    if (s == null || s.length() < 1) return "";
    int start = 0, end = 0;
    for (int i = 0; i < s.length(); i++) {
        int len1 = expandAroundCenter(s, i, i);
        int len2 = expandAroundCenter(s, i, i + 1);
        int len = Math.max(len1, len2);
        if (len > end - start) {
            start = i - (len - 1) / 2;
            end = i + len / 2;
        }
    }
    return s.substring(start, end + 1);
}

private int expandAroundCenter(String s, int left, int right) {
    int L = left, R = right;
    while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
        L--;
        R++;
    }
    return R - L - 1;
}

public boolean isPalindromic(String s) {
		int len = s.length();
		for (int i = 0; i < len / 2; i++) {
			if (s.charAt(i) != s.charAt(len - i - 1)) {
				return false;
			}
		}
		return true;
	}
public String longestPalindrome(String s) {
    String ans = "";
    int max = 0;
    int len = s.length();
    for (int i = 0; i < len; i++)
        for (int j = i + 1; j <= len; j++) {
            String test = s.substring(i, j);
            if (isPalindromic(test) && test.length() > max) {
                ans = s.substring(i, j);
                max = Math.max(max, ans.length());
            }
        }
    return ans;
}

4、矩阵中的最长递增路径,可以上下左右一起都走; leetcode329

public class Solution {
  private static final int[][] dirs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
  private int m, n;

  public int longestIncreasingPath(int[][] matrix) {
      if (matrix.length == 0) return 0;
      m = matrix.length;
      n = matrix[0].length;
      int ans = 0;
      for (int i = 0; i < m; ++i)
          for (int j = 0; j < n; ++j)
              ans = Math.max(ans, dfs(matrix, i, j));
      return ans;
  }

  private int dfs(int[][] matrix, int i, int j) {
      int ans = 0;
      for (int[] d : dirs) {
          int x = i + d[0], y = j + d[1];
          if (0 <= x && x < m && 0 <= y && y < n && matrix[x][y] > matrix[i][j])
              ans = Math.max(ans, dfs(matrix, x, y));
      }
      return ++ans;
  }
}

5、判断一个二叉树是另一个二叉树的子树

public boolean isSubtree(TreeNode s, TreeNode t) {
    if (s == null) return false;
    return isSubtreeWithRoot(s, t) || isSubtree(s.left, t) || isSubtree(s.right, t);
}

private boolean isSubtreeWithRoot(TreeNode s, TreeNode t) {
    if (t == null && s == null) return true;
    if (t == null || s == null) return false;
    if (t.val != s.val) return false;
    return isSubtreeWithRoot(s.left, t.left) && isSubtreeWithRoot(s.right, t.right);
}

6、归并排序的时间复杂度 // NlongN

  1. 归并方法
    归并方法将数组中两个已经排序的部分归并成一个。
public abstract class MergeSort<T extends Comparable<T>> extends Sort<T> {

    protected T[] aux;


    protected void merge(T[] nums, int l, int m, int h) {

        int i = l, j = m + 1;

        for (int k = l; k <= h; k++) {
            aux[k] = nums[k]; // 将数据复制到辅助数组
        }

        for (int k = l; k <= h; k++) {
            if (i > m) {
                nums[k] = aux[j++];

            } else if (j > h) {
                nums[k] = aux[i++];

            } else if (aux[i].compareTo(aux[j]) <= 0) {
                nums[k] = aux[i++]; // 先进行这一步,保证稳定性

            } else {
                nums[k] = aux[j++];
            }
        }
    }
}
  1. 自顶向下归并排序
    将一个大数组分成两个小数组去求解。

因为每次都将问题对半分成两个子问题,这种对半分的算法复杂度一般为 O(NlogN)。

public class Up2DownMergeSort<T extends Comparable<T>> extends MergeSort<T> {

    @Override
    public void sort(T[] nums) {
        aux = (T[]) new Comparable[nums.length];
        sort(nums, 0, nums.length - 1);
    }

    private void sort(T[] nums, int l, int h) {
        if (h <= l) {
            return;
        }
        int mid = l + (h - l) / 2;
        sort(nums, l, mid);
        sort(nums, mid + 1, h);
        merge(nums, l, mid, h);
    }
}
  1. 自底向上归并排序
    先归并那些微型数组,然后成对归并得到的微型数组。
public class Down2UpMergeSort<T extends Comparable<T>> extends MergeSort<T> {

    @Override
    public void sort(T[] nums) {

        int N = nums.length;
        aux = (T[]) new Comparable[N];

        for (int sz = 1; sz < N; sz += sz) {
            for (int lo = 0; lo < N - sz; lo += sz + sz) {
                merge(nums, lo, lo + sz - 1, Math.min(lo + sz + sz - 1, N - 1));
            }
        }
    }
}

7、求给出01矩阵中的最大正方形面积(全为1) lc221

8、求二叉树中距离最远的节点 leetcode543

private int max = 0;

public int diameterOfBinaryTree(TreeNode root) {
    depth(root);
    return max;
}

private int depth(TreeNode root) {
    if (root == null) return 0;
    int leftDepth = depth(root.left);
    int rightDepth = depth(root.right);
    max = Math.max(max, leftDepth + rightDepth);
    return Math.max(leftDepth, rightDepth) + 1;
}
class Solution {
    int ans;
    public int diameterOfBinaryTree(TreeNode root) {
        ans = 1;
        depth(root);
        return ans - 1;
    }
    public int depth(TreeNode node) {
        if (node == null) return 0; // 访问到空节点了,返回0
        int L = depth(node.left); // 左儿子为根的子树的深度
        int R = depth(node.right); // 右儿子为根的子树的深度
        ans = Math.max(ans, L+R+1); // 计算d_node即L+R+1 并更新ans
        return Math.max(L, R) + 1; // 返回该节点为根的子树的深度
    }
}

9、判断字符串是否为合法IPV4地址 lc468

class Solution {
  public String validateIPv4(String IP) {
    String[] nums = IP.split("\\.", -1);
    for (String x : nums) {
      // Validate integer in range (0, 255):
      // 1. length of chunk is between 1 and 3
      if (x.length() == 0 || x.length() > 3) return "Neither";
      // 2. no extra leading zeros
      if (x.charAt(0) == '0' && x.length() != 1) return "Neither";
      // 3. only digits are allowed
      for (char ch : x.toCharArray()) {
        if (! Character.isDigit(ch)) return "Neither";
      }
      // 4. less than 255
      if (Integer.parseInt(x) > 255) return "Neither";
    }
    return "IPv4";
  }

  public String validateIPv6(String IP) {
    String[] nums = IP.split(":", -1);
    String hexdigits = "0123456789abcdefABCDEF";
    for (String x : nums) {
      // Validate hexadecimal in range (0, 2**16):
      // 1. at least one and not more than 4 hexdigits in one chunk
      if (x.length() == 0 || x.length() > 4) return "Neither";
      // 2. only hexdigits are allowed: 0-9, a-f, A-F
      for (Character ch : x.toCharArray()) {
        if (hexdigits.indexOf(ch) == -1) return "Neither";
      }
    }
    return "IPv6";
  }

  public String validIPAddress(String IP) {
    if (IP.chars().filter(ch -> ch == '.').count() == 3) {
      return validateIPv4(IP);
    }
    else if (IP.chars().filter(ch -> ch == ':').count() == 7) {
      return validateIPv6(IP);
    }
    else return "Neither";
  }
}


10、数组值为1-n,各出现一次,先加入x(x也是1-n的范围),找出x

11、给定n,计算15n,不用+*/

**

12、给定字符数组chars,将其右移n位

**

public String LeftRotateString(String str, int n) {
    if (n >= str.length())
        return str;
    char[] chars = str.toCharArray();
    reverse(chars, 0, n - 1);
    reverse(chars, n, chars.length - 1);
    reverse(chars, 0, chars.length - 1);
    return new String(chars);
}

private void reverse(char[] chars, int i, int j) {
    while (i < j)
        swap(chars, i++, j--);
}

private void swap(char[] chars, int i, int j) {
    char t = chars[i];
    chars[i] = chars[j];
    chars[j] = t;
}

**

13、100层楼,只有两个鸡蛋,找出鸡蛋会在哪一层楼被摔碎

扔鸡蛋问题
扔鸡蛋问题

14、reverse linked list in a group of k**

public ListNode FindKthToTail(ListNode head, int k) {
    if (head == null)
        return null;
    ListNode P1 = head;
    while (P1 != null && k-- > 0)
        P1 = P1.next;
    if (k > 0)
        return null;
    ListNode P2 = head;
    while (P1 != null) {
        P1 = P1.next;
        P2 = P2.next;
    }
    return P2;
}

15、如何空间O(0)实现两个数的互换

a = a ^ b;
b = a ^ b;
a = a ^ b;

16、IP地址的Regex

17、the longest path in a binary tree lc124

class Solution {
	public int maxPathSum(TreeNode root) {
		int[] maxSum = new int[1]; //创建一个引用来记录当前记录最大值
		maxSum[0] = Integer.MIN_VALUE;//设置默认路径最小,遇到负数才能更新成更小的负数。
		maxPathSumHelper(root, maxSum);
		return maxSum[0];
	}

	public int maxPathSumHelper(TreeNode root, int[] maxSum) {
		if (root == null) {
			return 0;
		}
		int nSum = root.val;//当前节点的值
		int lSum = maxPathSumHelper(root.left, maxSum);//左侧返回的最大值
		int rSum = maxPathSumHelper(root.right, maxSum);//右侧返回的最大值
		if (lSum < 0) {//如果左侧最大值还小于0,则放弃左边这条路径和
			lSum = 0;
		}
		if (rSum < 0) {//如果右侧最大值还小于0,则放弃右边这条路径和
			rSum = 0;
		}
		int aSum = nSum + lSum + rSum;//将左右两边连接成一条线,形成一条完成的路径
		maxSum[0] = Math.max(aSum, maxSum[0]);//更新最大值
		return nSum + Math.max(rSum, lSum);//返回比较大的路径,因为我们以当前节点的连线是一条单一的路径,看文章开头。
	}
}

18、the largest consecutive sum in an array

public int FindGreatestSumOfSubArray(int[] nums) {
    if (nums == null || nums.length == 0)
        return 0;
    int greatestSum = Integer.MIN_VALUE;
    int sum = 0;
    for (int val : nums) {
        sum = sum <= 0 ? val : sum + val;
        greatestSum = Math.max(greatestSum, sum);
    }
    return greatestSum;
}

19、LeetCode 41 Find mis sing positive

import java.util.HashSet;
import java.util.Set;

public class Solution {

    public int firstMissingPositive(int[] nums) {
        int len = nums.length;

        Set<Integer> hashSet = new HashSet<>();
        for (int num : nums) {
            hashSet.add(num);
        }

        for (int i = 1; i <= len ; i++) {
            if (!hashSet.contains(i)){
                return i;
            }
        }

        return len + 1;
    }
}

20、给一个小于一亿的中文数字字符串,转化成数字格式

21、一个数组,把所有的0都移动到末尾,还要保持顺序不乱 维持临界点j,如果当前遍历不是0,就和j互换

public void moveZeroes(int[] nums) {
    int idx = 0;
    for (int num : nums) {
        if (num != 0) {
            nums[idx++] = num;
        }
    }
    while (idx < nums.length) {
        nums[idx++] = 0;
    }
}

22、罗马数字转整数 leetcode13

import java.util.*;

class Solution {
    public int romanToInt(String s) {
        int sum = 0;
        int preNum = getValue(s.charAt(0));
        for(int i = 1;i < s.length(); i ++) {
            int num = getValue(s.charAt(i));
            if(preNum < num) {
                sum -= preNum;
            } else {
                sum += preNum;
            }
            preNum = num;
        }
        sum += preNum;
        return sum;
    }
    
    private int getValue(char ch) {
        switch(ch) {
            case 'I': return 1;
            case 'V': return 5;
            case 'X': return 10;
            case 'L': return 50;
            case 'C': return 100;
            case 'D': return 500;
            case 'M': return 1000;
            default: return 0;
        }
    }
}

23、二叉树的序列化和反序列化

String Serialize(TreeNode root){
    if(root==null) return "";
    return helpSerialize(root,new StringBuilder().toString());
}

Private StringBuilder helpSerialize(TreeNode root,SttringBuilder s){
    if(root==null)return s;
    s.append(root.val).append("!")if(root.left!=null){
            helpSerialize(root.left,s);
            else{
                s.apped("#!");
            }
            if(root.right!=null){
                helpSerialize(root.right,s);
            }else{
                s.append("#!");
            }
            return s;
        }
}

24、输入一个数组,输出数组中满足条件的数字,条件为:数组中当前元素的值大于等于它前面所有的元素,小于等于它后面所有的元素。

25、给出一个数字,对数字的两位进行交换,只能交换一次,输出可能结果中的最小数字

26、输入一个字符串,字符串中字符全部为数字,在字符串中插入 ‘.’ 使得结果为合法的ip地址,输出全部可能的结果

27、基数排序

28、链表是否为回文结构。不能用栈*

public boolean isPalindrome(ListNode head) {
    if (head == null || head.next == null) return true;
    ListNode slow = head, fast = head.next;
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    if (fast != null) slow = slow.next;  // 偶数节点,让 slow 指向下一个节点
    cut(head, slow);                     // 切成两个链表
    return isEqual(head, reverse(slow));
}

private void cut(ListNode head, ListNode cutNode) {
    while (head.next != cutNode) {
        head = head.next;
    }
    head.next = null;
}

private ListNode reverse(ListNode head) {
    ListNode newHead = null;
    while (head != null) {
        ListNode nextNode = head.next;
        head.next = newHead;
        newHead = head;
        head = nextNode;
    }
    return newHead;
}

private boolean isEqual(ListNode l1, ListNode l2) {
    while (l1 != null && l2 != null) {
        if (l1.val != l2.val) return false;
        l1 = l1.next;
        l2 = l2.next;
    }
    return true;
}

29、最大不重复子串

public int longestSubStringWithoutDuplication(String str) {
    int curLen = 0;
    int maxLen = 0;
    int[] preIndexs = new int[26];
    Arrays.fill(preIndexs, -1);
    for (int curI = 0; curI < str.length(); curI++) {
        int c = str.charAt(curI) - 'a';
        int preI = preIndexs[c];
        if (preI == -1 || curI - preI > curLen) {
            curLen++;
        } else {
            maxLen = Math.max(maxLen, curLen);
            curLen = curI - preI;
        }
        preIndexs[c] = curI;
    }
    maxLen = Math.max(maxLen, curLen);
    return maxLen;
}

30、复杂链表复制

31、长度为n的数组,元素大小是0~n-1,判断数组元素是否有重复的

public boolean duplicate(int[] nums, int length, int[] duplication) {
    if (nums == null || length <= 0)
        return false;
    for (int i = 0; i < length; i++) {
        while (nums[i] != i) {
            if (nums[i] == nums[nums[i]]) {
                duplication[0] = nums[i];
                return true;
            }
            swap(nums, i, nums[i]);
        }
    }
    return false;
}

private void swap(int[] nums, int i, int j) {
    int t = nums[i];
    nums[i] = nums[j];
    nums[j] = t;
}

32、list1/list2交替打印元素


public void listTest() {
    List<String> source1 = Arrays.asList("1", "2", "3");//源list1
    List<String> source2 = Arrays.asList("a", "b", "c", "d");//源list2
    //计算较大的数组长度
    int max = source1.size() > source1.size() ? source1.size() : source2.size();
    //新建一个数组list,来接受最终结果
    List<String> list = new ArrayList<>(source1.size() + source1.size());
    //遍历较大长度,保证所有数据都能取到
    for (int i = 0; i < max; i++) {
        if (i < source1.size()) {
            list.add(source1.get(i));
        }
 
        if (i < source2.size()) {
            list.add(source2.get(i));
        }
    }
    //打印结果
    System.out.println(list);
}

33、36进制加法

34、合并区间

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        if (!intervals.size()) return {};

        //先把区间集合按照左端点从小到大进行排序
        sort(intervals.begin(), intervals.end(), less<vector<int>>());
        int pos = 0;//pos的值是每个不重叠的区间
        
        //从第二个区间开始去比较
        for (int i = 1; i < intervals.size(); ++i) 
        {
            //两个区间若能合并,则第一个区间的右端点一定大于等于第二个区间的左端点
            //比如[1,3] [2,6]
            if (intervals[pos][1] >= intervals[i][0]) 
            {
                //第一个区间的尾部需要更新为:两个区间的最大值即[1,6]
                intervals[pos][1] = max(intervals[pos][1], intervals[i][1]);
            } 
            else//没有重叠时 
            {
                //[1,6] [2,8]====>区间1就是目前的这个区间
                intervals[++pos] = intervals[i];
            }
        }

        intervals.resize(pos + 1);
        return intervals;
    }
   
};
class Solution {
    private class IntervalComparator implements Comparator<Interval> {
        @Override
        public int compare(Interval a, Interval b) {
            return a.start < b.start ? -1 : a.start == b.start ? 0 : 1;
        }
    }

    public List<Interval> merge(List<Interval> intervals) {
        Collections.sort(intervals, new IntervalComparator());

        LinkedList<Interval> merged = new LinkedList<Interval>();
        for (Interval interval : intervals) {
            // if the list of merged intervals is empty or if the current
            // interval does not overlap with the previous, simply append it.
            if (merged.isEmpty() || merged.getLast().end < interval.start) {
                merged.add(interval);
            }
            // otherwise, there is overlap, so we merge the current and previous
            // intervals.
            else {
                merged.getLast().end = Math.max(merged.getLast().end, interval.end);
            }
        }

        return merged;
    }
}
class Solution {
    private class IntervalComparator implements Comparator<Interval> {
        @Override
        public int compare(Interval a, Interval b) {
            return a.start < b.start ? -1 : a.start == b.start ? 0 : 1;
        }
    }

    public List<Interval> merge(List<Interval> intervals) {
        Collections.sort(intervals, new IntervalComparator());

        LinkedList<Interval> merged = new LinkedList<Interval>();
        for (Interval interval : intervals) {
            // if the list of merged intervals is empty or if the current
            // interval does not overlap with the previous, simply append it.
            if (merged.isEmpty() || merged.getLast().end < interval.start) {
                merged.add(interval);
            }
            // otherwise, there is overlap, so we merge the current and previous
            // intervals.
            else {
                merged.getLast().end = Math.max(merged.getLast().end, interval.end);
            }
        }

        return merged;
    }
}

35、快排

public class QuickSort<T extends Comparable<T>> extends Sort<T> {

    @Override
    public void sort(T[] nums) {
        shuffle(nums);
        sort(nums, 0, nums.length - 1);
    }

    private void sort(T[] nums, int l, int h) {
        if (h <= l)
            return;
        int j = partition(nums, l, h);
        sort(nums, l, j - 1);
        sort(nums, j + 1, h);
    }

    private void shuffle(T[] nums) {
        List<Comparable> list = Arrays.asList(nums);
        Collections.shuffle(list);
        list.toArray(nums);
    }
}
  private int partition(T[] nums, int l, int h) {
    int i = l, j = h + 1;
    T v = nums[l];
    while (true) {
        while (less(nums[++i], v) && i != h) ;
        while (less(v, nums[--j]) && j != l) ;
        if (i >= j)
            break;
        swap(nums, i, j);
    }
    swap(nums, l, j);
    return j;
}

36、生产者-消费者 模型

public class ProducerConsumer {

    private static BlockingQueue<String> queue = new ArrayBlockingQueue<>(5);

    private static class Producer extends Thread {
        @Override
        public void run() {
            try {
                queue.put("product");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.print("produce..");
        }
    }

    private static class Consumer extends Thread {

        @Override
        public void run() {
            try {
                String product = queue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.print("consume..");
        }
    }
}

public static void main(String[] args) {
    for (int i = 0; i < 2; i++) {
        Producer producer = new Producer();
        producer.start();
    }
    for (int i = 0; i < 5; i++) {
        Consumer consumer = new Consumer();
        consumer.start();
    }
    for (int i = 0; i < 3; i++) {
        Producer producer = new Producer();
        producer.start();
    }
}
produce..produce..consume..consume..produce..consume..produce..consume..produce..consume..

37、排序一个字符串时间要求O(n)

private ArrayList<String> ret = new ArrayList<>();

public ArrayList<String> Permutation(String str) {
    if (str.length() == 0)
        return ret;
    char[] chars = str.toCharArray();
    Arrays.sort(chars);
    backtracking(chars, new boolean[chars.length], new StringBuilder());
    return ret;
}

private void backtracking(char[] chars, boolean[] hasUsed, StringBuilder s) {
    if (s.length() == chars.length) {
        ret.add(s.toString());
        return;
    }
    for (int i = 0; i < chars.length; i++) {
        if (hasUsed[i])
            continue;
        if (i != 0 && chars[i] == chars[i - 1] && !hasUsed[i - 1]) /* 保证不重复 */
            continue;
        hasUsed[i] = true;
        s.append(chars[i]);
        backtracking(chars, hasUsed, s);
        s.deleteCharAt(s.length() - 1);
        hasUsed[i] = false;
    }
}

38、给一个有重复数字的数组,求集合{(a,b,c) | a+b+c=0}

public static List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> list = new ArrayList<List<Integer>>();
        Arrays.sort(nums);
        for (int i = 0; i < nums.length - 1; i++) {
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            int left = i + 1;
            int right = nums.length - 1;
            while (left < right) {
                if (nums[left] + nums[right] + nums[i] > 0) {
                    right--;
                } else if (nums[left] + nums[right] + nums[i] < 0) {
                    left++;
                } else {
                    list.add(Arrays.asList(nums[left], nums[right], nums[i]));
                    left++;
                    right--;
                    while (left < right && nums[left] == nums[left - 1]) {
                        left++;
                    }
                    while (left < right && nums[right] == nums[right + 1]) {
                        right--;
                    }
                }

            }
        }
        return list;
    }

数组中重复的数字

(1)hash表

public static void main(String[] args) {
    int [] data={2,3,1,0,2,5,3};
    HashMap<Integer,Integer> map=new HashMap<>();
    for(int i=0;i<data.length;i++){
        if(map.containsKey(data[i])){
            map.put(data[i],map.get(data[i])+1);
        }else
            map.put(data[i],1);
    }
    map.forEach((key,value)->{
        if(value>1)
            System.out.println(key+" : "+value);
    });
}

(2)技巧

public static void main(String[] args) {
    int [] data={2,3,1,0,2,4,4,5,4,4,3,1,2,3};
    //map用来统计个数
    Map<Integer,Integer> map=new HashMap<>();

    for(int i=0;i<data.length;i++){
        //因为要统计个数我加了个条件和书上不太一样
        //data[i]!=-1
        while(data[i]!=i&&data[i]!=-1) {
            //说明重复
            if (data[data[i]] == data[i]) {
                if (map.containsKey(data[i])) {
                    map.put(data[i], map.get(data[i])+1);
                } else {
                    map.put(data[i], 2);
                }
                //因为改位置上的值为重复值,将他置为-1是为了统计重复数字出现次数
                data[i] = -1;
                break;
            } else {
                int temp = data[i];
                data[i] = data[data[i]];
                data[temp] = temp;
            }
        }
    }
    map.forEach((key,value)->{
        System.out.println(key+" : " +value );
    });
}

39、两个栈实现队列

class MyQueue {

    private Stack<Integer> in = new Stack<>();
    private Stack<Integer> out = new Stack<>();

    public void push(int x) {
        in.push(x);
    }

    public int pop() {
        in2out();
        return out.pop();
    }

    public int peek() {
        in2out();
        return out.peek();
    }

    private void in2out() {
        if (out.isEmpty()) {
            while (!in.isEmpty()) {
                out.push(in.pop());
            }
        }
    }

    public boolean empty() {
        return in.isEmpty() && out.isEmpty();
    }
}

40、二叉树转化为双端链表

41、手写线程池

public class CountdownLatchExample {

    public static void main(String[] args) throws InterruptedException {
        final int totalThread = 10;
        CountDownLatch countDownLatch = new CountDownLatch(totalThread);
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < totalThread; i++) {
            executorService.execute(() -> {
                System.out.print("run..");
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        System.out.println("end");
        executorService.shutdown();
    }
}
run..run..run..run..run..run..run..run..run..run..end
public class CyclicBarrierExample {

    public static void main(String[] args) {
        final int totalThread = 10;
        CyclicBarrier cyclicBarrier = new CyclicBarrier(totalThread);
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < totalThread; i++) {
            executorService.execute(() -> {
                System.out.print("before..");
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
                System.out.print("after..");
            });
        }
        executorService.shutdown();
    }
}
before..before..before..before..before..before..before..before..before..before..after..after..after..after..after..after..after..after 

42、之字形打印二叉树

public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
    ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
    Queue<TreeNode> queue = new LinkedList<>();
    queue.add(pRoot);
    boolean reverse = false;
    while (!queue.isEmpty()) {
        ArrayList<Integer> list = new ArrayList<>();
        int cnt = queue.size();
        while (cnt-- > 0) {
            TreeNode node = queue.poll();
            if (node == null)
                continue;
            list.add(node.val);
            queue.add(node.left);
            queue.add(node.right);
        }
        if (reverse)
            Collections.reverse(list);
        reverse = !reverse;
        if (list.size() != 0)
            ret.add(list);
    }
    return ret;
}

43、给定一个数组,调整该数组,使其满足堆的性质

44、给定n个单词,如果单词组成一致但是元素顺序不一致,该对单词为同位词,例如:abc,bca为同位词.求所有同位词的集合输出

private ArrayList<String> ret = new ArrayList<>();

public ArrayList<String> Permutation(String str) {
    if (str.length() == 0)
        return ret;
    char[] chars = str.toCharArray();
    Arrays.sort(chars);
    backtracking(chars, new boolean[chars.length], new StringBuilder());
    return ret;
}

private void backtracking(char[] chars, boolean[] hasUsed, StringBuilder s) {
    if (s.length() == chars.length) {
        ret.add(s.toString());
        return;
    }
    for (int i = 0; i < chars.length; i++) {
        if (hasUsed[i])
            continue;
        if (i != 0 && chars[i] == chars[i - 1] && !hasUsed[i - 1]) /* 保证不重复 */
            continue;
        hasUsed[i] = true;
        s.append(chars[i]);
        backtracking(chars, hasUsed, s);
        s.deleteCharAt(s.length() - 1);
        hasUsed[i] = false;
    }
}

45、链表,两个链表的公共点

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    ListNode l1 = headA, l2 = headB;
    while (l1 != l2) {
        l1 = (l1 == null) ? headB : l1.next;
        l2 = (l2 == null) ? headA : l2.next;
    }
    return l1;
}

46、二叉树的后续遍历非递归形式

public List<Integer> postorderTraversal(TreeNode root) {
    List<Integer> ret = new ArrayList<>();
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        if (node == null) continue;
        ret.add(node.val);
        stack.push(node.left);
        stack.push(node.right);
    }
    Collections.reverse(ret);
    return ret;
}

47、买卖股票的最佳时机,只能一次买入和一次卖出

public int maxProfit(int[] prices) {
    if (prices == null || prices.length == 0)
        return 0;
    int soFarMin = prices[0];
    int maxProfit = 0;
    for (int i = 1; i < prices.length; i++) {
        soFarMin = Math.min(soFarMin, prices[i]);
        maxProfit = Math.max(maxProfit, prices[i] - soFarMin);
    }
    return maxProfit;
}

48、可以进行多次交易的结果,求赚取的最大利润

class Solution {
public:
    int maxProfit(vector<int>& prices) 
    {
        int n=prices.size();
        float result=0.0;
        for(int i=n-1;i>0;i--)
        result+=prices[i]>prices[i-1]?prices[i]-prices[i-1]:0;
        return result;
    }
};

49、(A,B)(A,C)(B,D)(D,A)判断是否有循环引用,提示用拓扑排序

50、数组找是否存在和为M的两个数


public int[] twoSum(int[] nums, int target) {
    for (int i = 0; i < nums.length; i++) {
        for (int j = i + 1; j < nums.length; j++) {
            if (nums[j] == target - nums[i]) {
                return new int[] { i, j };
            }
        }
    }
    throw new IllegalArgumentException("No two sum solution");
}
public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        map.put(nums[i], i);
    }
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (map.containsKey(complement) && map.get(complement) != i) {
            return new int[] { i, map.get(complement) };
        }
    }
    throw new IllegalArgumentException("No two sum solution");
}

public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (map.containsKey(complement)) {
            return new int[] { map.get(complement), i };
        }
        map.put(nums[i], i);
    }
    throw new IllegalArgumentException("No two sum solution");

51、KMP

52、实现一个阻塞队列(生产者消费者模型)

public class ProducerConsumer {

    private static BlockingQueue<String> queue = new ArrayBlockingQueue<>(5);

    private static class Producer extends Thread {
        @Override
        public void run() {
            try {
                queue.put("product");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.print("produce..");
        }
    }

    private static class Consumer extends Thread {

        @Override
        public void run() {
            try {
                String product = queue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.print("consume..");
        }
    }
}

public static void main(String[] args) {
    for (int i = 0; i < 2; i++) {
        Producer producer = new Producer();
        producer.start();
    }
    for (int i = 0; i < 5; i++) {
        Consumer consumer = new Consumer();
        consumer.start();
    }
    for (int i = 0; i < 3; i++) {
        Producer producer = new Producer();
        producer.start();
    }
}
produce..produce..consume..consume..produce..consume..produce..consume..produce..consume..

53、找出10000个数据中第 k 大的数

54、输入一个字符串,包含数字、加减乘除和括号,输出结果,编程

55、给定一个数x,要求使用k个数字求和可以得到x,数字从1-9中选择,不能重复。

56、输入一个正整数 N,返回 N 个 ‘(’ 和 N 个 ‘)’ 的所有可能情况

57、76.minimum-window-substring、30.substring-with-concatenation-of-all-words、42.trapping-rain-water,

public ArrayList<Integer> maxInWindows(int[] num, int size) {
    ArrayList<Integer> ret = new ArrayList<>();
    if (size > num.length || size < 1)
        return ret;
    PriorityQueue<Integer> heap = new PriorityQueue<>((o1, o2) -> o2 - o1);  /* 大顶堆 */
    for (int i = 0; i < size; i++)
        heap.add(num[i]);
    ret.add(heap.peek());
    for (int i = 0, j = i + size; j < num.length; i++, j++) {            /* 维护一个大小为 size 的大顶堆 */
        heap.remove(num[i]);
        heap.add(num[j]);
        ret.add(heap.peek());
    }
    return ret;
}

58、求树的最左下节点

public int findBottomLeftValue(TreeNode root) {
    Queue<TreeNode> queue = new LinkedList<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        root = queue.poll();
        if (root.right != null) queue.add(root.right);
        if (root.left != null) queue.add(root.left);
    }
    return root.val;
}

59、无序数组中第k大的数(quick select)

public T select(T[] nums, int k) {
    int l = 0, h = nums.length - 1;
    while (h > l) {
        int j = partition(nums, l, h);

        if (j == k) {
            return nums[k];

        } else if (j > k) {
            h = j - 1;

        } else {
            l = j + 1;
        }
    }
    return nums[k];
}
private int partition(T[] nums, int l, int h) {
    int i = l, j = h + 1;
    T v = nums[l];
    while (true) {
        while (less(nums[++i], v) && i != h) ;
        while (less(v, nums[--j]) && j != l) ;
        if (i >= j)
            break;
        swap(nums, i, j);
    }
    swap(nums, l, j);
    return j;
}

60、求旋转数组找最小值(二分)

public int findMin(int[] nums) {
    int l = 0, h = nums.length - 1;
    while (l < h) {
        int m = l + (h - l) / 2;
        if (nums[m] <= nums[h]) {
            h = m;
        } else {
            l = m + 1;
        }
    }
    return nums[l];
}

61、判断二叉树是否镜像(递归)

public boolean isSymmetric(TreeNode root) {
    if (root == null) return true;
    return isSymmetric(root.left, root.right);
}

private boolean isSymmetric(TreeNode t1, TreeNode t2) {
    if (t1 == null && t2 == null) return true;
    if (t1 == null || t2 == null) return false;
    if (t1.val != t2.val) return false;
    return isSymmetric(t1.left, t2.right) && isSymmetric(t1.right, t2.left);
}

62、给定一个矩阵,从左上角开始只能往下或者右走,求到达右下角的最小权值路径

public int minPathSum(int[][] grid) {
    if (grid.length == 0 || grid[0].length == 0) {
        return 0;
    }
    int m = grid.length, n = grid[0].length;
    int[] dp = new int[n];
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (j == 0) {
                dp[j] = dp[j];        // 只能从上侧走到该位置
            } else if (i == 0) {
                dp[j] = dp[j - 1];    // 只能从左侧走到该位置
            } else {
                dp[j] = Math.min(dp[j - 1], dp[j]);
            }
            dp[j] += grid[i][j];
        }
    }
    return dp[n - 1];
}
class Solution {
    public int minPathSum(int[][] grid) {
        for(int i = 0; i < grid.length; i++) {
            for(int j = 0; j < grid[0].length; j++) {
                if(i == 0 && j == 0) continue;
                else if(i == 0)  grid[i][j] = grid[i][j - 1] + grid[i][j];
                else if(j == 0)  grid[i][j] = grid[i - 1][j] + grid[i][j];
                else grid[i][j] = Math.min(grid[i - 1][j], grid[i][j - 1]) + grid[i][j];
            }
        }
        return grid[grid.length - 1][grid[0].length - 1];
    }
}

63、字符串转Int,如果越界就返回0

public int StrToInt(String str) {
    if (str == null || str.length() == 0)
        return 0;
    boolean isNegative = str.charAt(0) == '-';
    int ret = 0;
    for (int i = 0; i < str.length(); i++) {
        char c = str.charAt(i);
        if (i == 0 && (c == '+' || c == '-'))  /* 符号判定 */
            continue;
        if (c < '0' || c > '9')                /* 非法输入 */
            return 0;
        ret = ret * 10 + (c - '0');
    }
    return isNegative ? -ret : ret;
}

64、lc400

65、单向链表实现加法

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
    Stack<Integer> l1Stack = buildStack(l1);
    Stack<Integer> l2Stack = buildStack(l2);
    ListNode head = new ListNode(-1);
    int carry = 0;
    while (!l1Stack.isEmpty() || !l2Stack.isEmpty() || carry != 0) {
        int x = l1Stack.isEmpty() ? 0 : l1Stack.pop();
        int y = l2Stack.isEmpty() ? 0 : l2Stack.pop();
        int sum = x + y + carry;
        ListNode node = new ListNode(sum % 10);
        node.next = head.next;
        head.next = node;
        carry = sum / 10;
    }
    return head.next;
}

private Stack<Integer> buildStack(ListNode l) {
    Stack<Integer> stack = new Stack<>();
    while (l != null) {
        stack.push(l.val);
        l = l.next;
    }
    return stack;
}

66、打家劫舍

public int rob(int[] nums) {
    int pre2 = 0, pre1 = 0;
    for (int i = 0; i < nums.length; i++) {
        int cur = Math.max(pre2 + nums[i], pre1);
        pre2 = pre1;
        pre1 = cur;
    }
    return pre1;
}

67、收到礼物最大值

import java.util.*;
 
public class Bonus {
    public int getMost(int[][] board) {
         
        if(board == null || board.length==0){
            return 0;
        }
         
        for(int i=0;i<board.length;i++){
            for (int j = 0; j < board[0].length; j++) {
                if(i==0 && j==0){
                    // 奖金就是第一个格子本身
                }else if(i==0){
                    // 说明在第一行   第一行的奖金只能来自第一行左边的格子
                    // 奖金等于当前格子的奖金加上左边格子的奖金
                    board[0][j] += board[0][j-1];                                      
                }else if(j==0){
                    // 说明在第一列   第一列的奖金只能来自列的上面个格子
                    // 奖金等于当前格子的奖金加上上面格子的奖金
                    board[i][0] += board[i-1][0];                      
                }else {
                    // 来自上面或者左边的格子,选取最大奖金的。
                    // 最大奖金等于当前格子奖金加上左边或上面格子中奖金数大的那个
                    board[i][j] +=Math.max(board[i][j-1],board[i-1][j]);
                }
            }
        }
         
        // 增加通用型,直接用数据的长度吧
        return board[board.length-1][board[0].length-1];
 
    }
}

68、五张牌,其中大小鬼为癞子,牌面为 0,判断这五张牌是否能组成顺子

public boolean isContinuous(int[] nums) {

    if (nums.length < 5)
        return false;

    Arrays.sort(nums);

    // 统计癞子数量
    int cnt = 0;
    for (int num : nums)
        if (num == 0)
            cnt++;

    // 使用癞子去补全不连续的顺子
    for (int i = cnt; i < nums.length - 1; i++) {
        if (nums[i + 1] == nums[i])
            return false;
        cnt -= nums[i + 1] - nums[i] - 1;
    }

    return cnt >= 0;
}

69、给定一个字符串打印所有的子串,要求不重复

class GetSubstring{
    public static void main(String[] args){
        String str = "abbc";
        System.out.println(str);

        System.out.println("-------------");
        for(int i = 0; i < str.length(); i++){
            for (int j = i+1; j<=str.length(); j++){
                System.out.println(str.substring(i,j));

            }
        }
    }
}

70、自然数1-n,排一块组成的字符串,求第k位是什么。

71.如果a[0]<a[1],a[n-2]>a[n-1],那么请找出任意一个点使得a[i-1]<a[i]>a[i+1] 要求logN

72、a[-1]和a[n+1]设为负无穷大,二分查找找到数组中的一个峰值。

public class Solution {
    public int findPeakElement(int[] nums) {
        if(1 == nums.length){
            return 0;
        }
        for(int i = 0; i < nums.length; i++){
            if(i == 0){
                if(nums[0] > nums[1]){
                    return 0;
                }
            }else if(i == nums.length - 1){
                if(nums[nums.length - 1] > nums[nums.length - 2]){
                    return nums.length - 1;
                }
            }else{
                if(nums[i] > nums[i - 1] && nums[i] > nums[i + 1]){
                    return i;
                }
            }
        }
        return -1;
    }
}

73、如果有一组数字,按照“拿出第一个数在桌上并然后将下一个数放到队尾”一直操作直到数字全部放在桌子上,给你最后在桌子上的数字,请返回最开始数字的顺序。

74、有序数组找到第一个小于0的数和第一个大于0的数

75、合并两个排序数组并去重


package com.algorithm;
/*
 * 合并两个有序数组,合并之后还是有序的  并且去除重复的。
 * */
public class MergeAndSortArray {
 
	public static void main(String[] args) {
		int [] num1=new int[]{1,3,5,6,7};
		int [] num2=new int[]{3,5,6,8};
		merge(num1, num2);
	}
	private static void merge(int [] num1,int [] num2){
		int[] result=new int[num1.length+num2.length];
		int i=0,j=0,k=0;//定义三个变量。i  j  k分别控制num1 num2  result三个数组的下标
		while(i<num1.length && j< num2.length){//两个数组都不为空的时候
			if(num1[i]<num2[j]){//若num1的元素小,加入result
				result[k]=num1[i];
				i++;//num1的下标后移
				k++;//result的下标后移
			}else if(num1[i]==num2[j]){//若二者相等 这一步就是去重复。
				result[k]=num1[i];//这里两个数组的元素把哪个加入result都行
				k++;//result下标后移
				i++;//这里要注意的是  两个重复了,去重之后,两个数组的下标都要后移
				j++;
			}else {
				result[k]=num2[j];//若num2的元素小,加入result
				k++;
				j++;
			}	
		}
		

		//下面是当其中一个数组元素全部添加到result了,另一个还没添加完  继续添加。
		while(i<num1.length){//
			result[k]=num1[i];
			i++;
			k++;
		}
		while(j<num2.length){
			result[k]=num2[j];
			j++;
			k++;
		}
		for (int num : result) {
			System.out.println(num);
		}
	}

76、两个排序数组找中位数

77、两个超大整数的字符串做减法运算。

78、1~10000中7出现的次数,如17算1个,77算2个。

79、给一个字符串数组,统计每一个字符串出现的次数,要求不能用set,map.时间复杂度O(n).

80、手撕最大堆,实现对应的push和pop操作


```java
package queue;

import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Comparator;

public class MaxHeapTest {

    public static void main(String[] args) {
        int[] num = {4,5,1,6,2,7,3,8};

        List<Integer> result = GetLeastNumbers_Solution(num,4);

        result.stream().forEach(System.out::println);
    }

    public static ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        int length = input.length;
        if(k > length || k == 0){
            return result;
        }
        //最大堆
        PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(k, new Comparator<Integer>() {

            @Override
            public int compare(Integer o1, Integer o2) {
                return o2.compareTo(o1);
            }
        });

        for (int i = 0; i < length; i++) {
            if (maxHeap.size() != k) {
                maxHeap.offer(input[i]);
            } else if (maxHeap.peek() > input[i]) {
                Integer temp = maxHeap.poll();
                temp = null;
                maxHeap.offer(input[i]);
            }
        }
        for (Integer integer : maxHeap) {
            result.add(integer);
        }
        return result;
    }
}

public class MaxHeap<E extends Comparable<E>> {
 
    private Array<E> data;
 
    //动态数组:用户向堆存放元素
    public MaxHeap(int capacity){
        //初始化动态数组
        data = new Array<>(capacity);
    }
 
    public MaxHeap(){
        data = new Array<>();
    }
 
    // 返回堆中的元素个数
    public int size(){
        return data.getSize();
    }
 
    // 返回一个布尔值, 表示堆中是否为空
    public boolean isEmpty(){
        return data.isEmpty();
    }
 
    // 返回完全二叉树的数组表示中,一个索引所表示的元素的父亲节点的索引
    private int parent(int index){
        if(index == 0) {
            throw new IllegalArgumentException("index-0 doesn't have parent.");
        }
        return (index - 1) / 2;
    }
 
    // 返回完全二叉树的数组表示中,一个索引所表示的元素的左孩子节点的索引
    private int leftChild(int index){
        return index * 2 + 1;
    }
 
    // 返回完全二叉树的数组表示中,一个索引所表示的元素的右孩子节点的索引
    private int rightChild(int index){
        return index * 2 + 2;
    }
}
public class Heap<T extends Comparable<T>> {

    private T[] heap;
    private int N = 0;

    public Heap(int maxN) {
        this.heap = (T[]) new Comparable[maxN + 1];
    }

    public boolean isEmpty() {
        return N == 0;
    }

    public int size() {
        return N;
    }

    private boolean less(int i, int j) {
        return heap[i].compareTo(heap[j]) < 0;
    }

    private void swap(int i, int j) {
        T t = heap[i];
        heap[i] = heap[j];
        heap[j] = t;
    }
}

```java
private void swim(int k) {
    while (k > 1 && less(k / 2, k)) {
        swap(k / 2, k);
        k = k / 2;
    }
}

81、找出一个字符串中所有的回文子串

public static ArrayList<String> findAllHuiWen2(String s){
    ArrayList<String> list = new ArrayList<String>();
    if(s==null || s.length()==0) return list;
    if(s.length()==1) {
        list.add(s);
        return list;
    }
    for(int i=0; i<s.length(); i++){
        getSubList(s,i,i,list);
        getSubList(s,i,i+1,list);
    }
    return list;
}

public static void getSubList(String s, int left, int right, ArrayList<String> list){
    while (left>=0 && right<s.length() && s.charAt(left)==s.charAt(right)){
        String subString = s.substring(left, right+1);
        if(!list.contains(subString))
            list.add(subString);
        left--;
        right++;
    }
}

void getAllSubstrings(String str){
        if(str.length==0)
                 return;
         else{
         for(int i=0;i<str.length;i++)
        {
           for(int j=i;j<str.length-1;j++)
           {  System.println(str.substring(i,i+j);}
         }     
         }
}

82、重复次数最多的最长连续子串(即找到重复次数最多的子串,若有多个,输出最长的)

83、长度为n的数组,有一个长度为k的滑动窗口,询问各个滑动窗口内的中位数。

84、区间最大最小值。两个长度为n的序列a,b,问有多少区间[l,r] 满足max(a[l,r])<min(b[l,r])。即a[l,r]的最大值小于b[l,r]的最小值

85、8皇后问题共有多少种解法

86、一个数字串删除指定个数的数字字符,剩下的组成一个最大的数

    private static int[] solution(int[] array, int k) {
        if (null == array || array.length == 0 || k <= 0) {
            return array;
        }
 
        int newLenth = array.length - k;
        int start = 0;
        int end = 1;
        while (end < array.length && k > 0) {
            if (start < 0 || array[end] <= array[start]) {
                array[start + 1] = array[end];
                start++;
                end++;
            } else {
                start--;
                k--;
            }
        }
        array[start + 1] = array[end];
 
        int[] result = new int[newLenth];
        for (int i = 0; i < newLenth; i++) {
            result[i] = array[i];
        }
 
        return result;
    }

87、N个长度为K的有序链表合并,时间复杂度,空间复杂度

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        int len = lists.length;//每次待处理的链表个数
        if(len==0)return null;//处理null

        while(len>1){
            int i;
            //两两合并,注意到这里将位置2i与2i+1的两个链表合并到位置i上。
            //如有不清楚的可以自己画个数组看看
            for( i = 0;i <len/2;i++){
                lists[i]=mergeTwoLists(lists[2*i],lists[2*i+1])   
            }
            //处理奇数的情况。把最后一个链表放到下次待求解数组的末端,顺便解决向上取整的问题
            if((len%2)!=0){
                lists[i]=lists[len-1];
                len++;
            }

            //规模减半
            len/=2;

        }

        return lists[0];
    }

    public  ListNode mergeTwoLists(ListNode l1,ListNode l2){
        ListNode head = new ListNode(-1);
        ListNode prev = head;
        while(l1!=null||l2!=null){
            if(l1==null){
                prev.next = l2;
                return head.next;
            }
            if(l2==null){
                prev.next = l1;
                return head.next;
            }
            if(l1.val<l2.val){
                prev.next = l1;
                l1 = l1.next;
            }
            else{
                prev.next = l2;
                l2 = l2.next;   
            }
                prev = prev.next;
        }
        
        return  head.next;
    }

    
}

88、N个长度为K的有序数组合并,时间复杂度,空间复杂度

89、用一个栈去排序另一个栈

90、一个数组实现两个栈

91、一个n位数,现在可以删除其中任意k位,使得剩下的数最小

92、实现有符号大数链表加法,靠近头结点位置为高位

public ListNode addTwoNumbers(ListNode first, ListNode second) {
        if(first==null)
            return second;
        if(second==null)
            return first;
        
        int sum=0;//first和second对应结点的和,值为(0-9);
        int carry=0;//first和second对应结点求和后对应的进位,值为(0或1);
        
        ListNode head=new ListNode(0);
        ListNode cur=head;
 
 
        while(first != null||second != null||carry != 0)
            {
            int num1=0;
            int num2=0;
            
            if(first!=null)
                {
                num1=first.val;
                first=first.next;
            }
            if(second!=null)
                {
                num2=second.val;
                second=second.next;
            }
            sum=(carry+num1+num2)%10;
            ListNode temp=new ListNode(sum);
            cur.next=temp;
            cur=cur.next;
            
            carry=(carry+num1+num2)/10;    
        }
        return head.next;
    }

93、找出来数组中每个元素后边第一个比它大的值

import java.util.Stack;
 
public class FindFirstBiggerNum {
    public static void main(String[] arg) {
        int array[]=new int[] {1,5,3,6,4,8,9,10};
        int res[]=findMax(array);
        for(int num:res) {
            System.out.println(num);
        }
 
    }
    public static int[] findMax(int[] array) {
        int len =array.length;
        Stack<Integer> st = new Stack<Integer>();
        int res[]=new int[len];
        int i=0;
        while(i<len) {
            if(st.isEmpty()||array[i]<=array[st.peek()]) {
                st.push(i);
                i++;
            }else {
                res[st.pop()]=array[i];
 
            }
        }
        while(!st.isEmpty()) {
            res[st.pop()]=-1;
        }
        return res;
    }
 
}

94、完全二叉树的最大深度与节点个数


class Solution {
    public int countNodes(TreeNode root) {
        if (root == null)
            return 0;
        
        int count = 0;
        count++;
        count += countNodes(root.left);
        count += countNodes(root.right);
        return count;
    }
        // 完全二叉树的高度可以直接通过不断地访问左子树就可以获取
    private int getDepth(TreeNode r) {
        int depth = 0;
        while(r != null) {
            depth++;
            r = r.left;
        }
        return depth;

95、两个有序数组交集、并集

//求两个有序数组的交集
	static int getIntersection(int array_1[],int len1,int array_2[],int len2,List<Integer> c) {
		int i = 0, j = 0, k = 0;
		while(i < len1 || j <len2) {
			if(array_1[i] == array_2[j]) {
				c.add(array_1[i]);
				i++;
				j++;
				k++;
			}else if(array_1[i] > array_2[j]) {
				j++;
			}else if(array_1[i] < array_2[j]) {
				i++;
			}
		
		}
		return k;
		
	}


 void unionsection(const vector<int>& v1,const vector<int>& v2,vector<int>& des)//求并集  
    {  
        int i,j;  
        i = j = 0;//定位到2个有序向量的头部  
         
        des.clear();  
        //必有一个向量插入完成  
        while(i < v1.size() && j < v2.size())  
        {  
            if(v1[i] == v2[j])  
            {  
                des.push_back(v1[i]);//相等则只压入容器一次,标记均后移一个位置,避免元素重复  
                i += 1;  
                j += 1;  
            }  
            else if(v1[i] < v2[j])//不相等则压入较小元素,标记后移一个位置  
            {  
                des.push_back(v1[i]);  
                i += 1;  
            }  
            else  
            {  
                des.push_back(v2[j]);  
                j += 1;  
            }  
        }   
  
        //对于部分未能压入向量中的元素,此处继续操作  
        while(i < v1.size())  
        {  
            des.push_back(v1[i]);  
            i++;  
        }  
 
        while(j < v2.size())  
        {  
            des.push_back(v2[j]);  
            j++;  
        }  
 
    } 

96、用二分法对一个数字开根号

public int mySqrt(int x) {
    if (x <= 1) {
        return x;
    }
    int l = 1, h = x;
    while (l <= h) {
        int mid = l + (h - l) / 2;
        int sqrt = x / mid;
        if (sqrt == mid) {
            return mid;
        } else if (mid > sqrt) {
            h = mid - 1;
        } else {
            l = mid + 1;
        }
    }
    return h;
}

97、一个无序有正有负数组,求乘积最大的三个数的乘积

public int maximumProduct(int[] nums) {
    int max1 = Integer.MIN_VALUE, max2 = Integer.MIN_VALUE, max3 = Integer.MIN_VALUE, min1 = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE;
    for (int n : nums) {
        if (n > max1) {
            max3 = max2;
            max2 = max1;
            max1 = n;
        } else if (n > max2) {
            max3 = max2;
            max2 = n;
        } else if (n > max3) {
            max3 = n;
        }

        if (n < min1) {
            min2 = min1;
            min1 = n;
        } else if (n < min2) {
            min2 = n;
        }
    }
    return Math.max(max1*max2*max3, max1*min1*min2);
}

98、实现链表,无序链表,对链表值奇偶分离并排序,空间复杂度O(1)

public ListNode oddEvenList(ListNode head) {
    if (head == null) {
        return head;
    }
    ListNode odd = head, even = head.next, evenHead = even;
    while (even != null && even.next != null) {
        odd.next = odd.next.next;
        odd = odd.next;
        even.next = even.next.next;
        even = even.next;
    }
    odd.next = evenHead;
    return head;
}

99、无序数组构建一棵二叉排序树

 public class Test86_BuildBSTByArray {
 4 
 5     public static void main(String[] args) {
 6         int[] a = {1,2,3,4,5};
 7         Test86_BuildBSTByArray app = new Test86_BuildBSTByArray();
 8         Node root = app.build(a, 0, a.length-1);
 9         System.out.println(root.value);
10     }
11     
12     Node build(int[] a, int start, int end){
13         if(start > end) return null;
14         int mid = start + (end - start) / 2;
15         Node root = new Node(a[mid]);
16         root.left = build(a, start, mid - 1);
17         root.right = build(a, mid+1,end);
18         return root;
19     }
20     
21     static class Node{
22         int value;
23         Node left;
24         Node right;
25         Node(int v){
26             this.value = v;
27         }
28     }
29 }

100、打印出根节点到叶子节点的最长路径

int BinaryTree :: Depth (BinTreeNode *t ) {
    if ( t == NULL ) return -1;
    else return 1 + Max ( Depth ( t→leftChild ),Depth ( t→rightChild ) );
}
public static int getDepth(TreeNode root){
        if(root==null){
            return 0;
        }else{
            //记录二叉树的高度
           int depth=0;
           //记录遍历到当前层的第几个节点
            int num=0;
            //记录当前层的节点个数
            int count=1;
            LinkedList<TreeNode> queue=new LinkedList<>();
            queue.add(root);
            while(!queue.isEmpty()){
                TreeNode node=queue.remove();
                num++;
                if(node.left!=null){
                    queue.add(node.left);
                }
                if(node.right!=null){
                    queue.add(node.right);
                }
                if(num==count){
                    depth++;
                    num=0;
                    count=queue.size();
                }
            }
           return depth;
        }
    }
  //先序遍历
    public void preOrderTraverse(TreeNode root){
        if(root==null){
            System.out.println("empty tree");
        }else{
            LinkedList<TreeNode> stack=new LinkedList();
            TreeNode node=root;
            while(!stack.isEmpty() || node!=null){
                if(node!=null){
                    System.out.print(node.val+" ");
                    stack.push(node);
                    node=node.left;
                }else{
                    TreeNode pNode=stack.pop();
                    node=pNode.right;
                }
            }
        }
    }
 
 
    //中序遍历
    public void midOrderTraverse(TreeNode root){
        if(root==null){
            System.out.println("empty tree");
        }else{
            LinkedList<TreeNode> stack=new LinkedList();
            TreeNode node=root;
            while(!stack.isEmpty() || node!=null){
                if(node!=null){
                    stack.push(node);
                    node=node.left;
                }else{
                    TreeNode pNode=stack.pop();
                    System.out.print(pNode.val+" ");
                    node=pNode.right;
                }
            }
        }
    }

101、字符串形式自定义进制大数相加

class Solution {
    public String addStrings(String num1, String num2) {
        StringBuilder res = new StringBuilder("");
        int i = num1.length() - 1, j = num2.length() - 1, carry = 0;
        while(i >= 0 || j >= 0){
            int n1 = i >= 0 ? num1.charAt(i) - '0' : 0;
            int n2 = j >= 0 ? num2.charAt(j) - '0' : 0;
            int tmp = n1 + n2 + carry;
            carry = tmp / 10;
            res.append(tmp % 10);
            i--; j--;
        }
        if(carry == 1) res.append(1);
        return res.reverse().toString();
    }
}

102、LeetCode 1038

private int sum = 0;

public TreeNode convertBST(TreeNode root) {
    traver(root);
    return root;
}

private void traver(TreeNode node) {
    if (node == null) return;
    traver(node.right);
    sum += node.val;
    node.val = sum;
    traver(node.left);
}
   // 记录最后一次访问的节点更新后的值,初始化为0
    private int lastVal = 0;

    public TreeNode bstToGst(TreeNode root) {
        traverse(root);
        return root;
    }

    private void traverse(TreeNode root) {
        if (root == null) {
            return;
        }
        // 1.遍历右子树
        traverse(root.right);

        // 2.访问当前节点. 加上前一个节点更新后的值,更新最后一次访问的节点值
        root.val += lastVal;
        lastVal = root.val;

        // 3.遍历左子树
        traverse(root.left);
    }

103、任意一个整型数组,判断是否可以将数组分为三个区间,每个区间中数值的和相同

简单生产消费者例子

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

class Producer extends Thread{
	BlockingQueue<String> queue;
	Producer(BlockingQueue<String> queue){
		this.queue=queue;
	}
	public void run() {
		int id=1;
		while(true) {
			try {
				queue.put("产品"+id);
				System.out.println("生产产品"+id);
				Thread.sleep(1000);
				id++;
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}
}
class Resumer extends Thread{
	BlockingQueue<String> queue;
	Resumer(BlockingQueue<String> queue){
		this.queue=queue;
	}
	public void run() {
		while(true) {
			try {
				System.out.println("取出"+queue.take());
				Thread.sleep(2500);
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
}
public class Test {
	
	public static void main(String[] args) {
		BlockingQueue<String> queue=new LinkedBlockingQueue<>(10);
		Producer producer=new Producer(queue);
		Resumer resumer=new Resumer(queue);
		producer.start();
		resumer.start();
	}

}


104、二叉树逆时针打印最外层节点

import java.util.ArrayList;
import java.util.Stack;
class TreeNode{
	TreeNode left;
	TreeNode right;
	int val;
	TreeNode(int val){
		this.val=val;
	}
}

public class Test {
    
    public static ArrayList<TreeNode> list = new ArrayList<TreeNode>();

    public static void getLeftSizeNodes(TreeNode root) {//遍历左边缘节点
        TreeNode node = root;
        while (node != null) {
        	list.add(node);
            node = node.left;
        }
    }
    
    public static void getBottomSizeNodes(TreeNode root) {//遍历底层叶子节点
        TreeNode node = root;
        if (node == null) {//根节点为空
            return;
        }
        getBottomSizeNodes(node.left);//递归根节点的左子树        
        if (node.left == null && node.right == null) {//如果当前节点是叶子节点
//这里拿当前节点和list最后一个元素做比较是为了防止重复输出(因为可能出现最左叶子节点和最底下的左边缘节点是同一个节点的情况)
            if (list.get(list.size() - 1) != node) {
                list.add(node);    
            }            
            return;
        }
        getBottomSizeNodes(node.right);//递归根节点的右子树
    }
    
    
    public static void getRightSizeNodes(TreeNode root) {//遍历右边缘节点
        TreeNode node = root;
        Stack<TreeNode> stack = new Stack<TreeNode>();//因为右边缘节点需要从下往上打印所以要用到栈
        
        node = node.right;
        while (node != null) {//遍历根节点的右子树及其右子树的右子树...
            stack.push(node);//非空则压栈
            node = node.right;
        }
        while (!stack.isEmpty()) {
            TreeNode n = stack.pop();//弹栈
//这里拿当前节点和list最后一个元素做比较是为了防止重复输出(因为可能出现最右叶子节点和最底下的右边缘节点是同一个节点的情况)
            if (list.get(list.size() - 1 ) != n) {
                list.add(n);
            }
        }
    }


	public static void main(String[] args) {
		 TreeNode root=new TreeNode(1);
		 TreeNode node2=new TreeNode(2);
		 TreeNode node3=new TreeNode(3);
		 TreeNode node4=new TreeNode(4);
		 TreeNode node5=new TreeNode(5);
		 TreeNode node6=new TreeNode(6);
		 TreeNode node7=new TreeNode(7);
		 root.left=node2;
		 root.right=node3;
		 node2.left=node4;
		 node2.right=node5;
		 node5.left=node7;
		 node3.right=node6;
		 getLeftSizeNodes(root);
	     getBottomSizeNodes(root);
	     getRightSizeNodes(root);
	     for(int i=0;i<list.size();i++) {
	    	 TreeNode node=list.get(i);
	    	 System.out.print(node.val+" ");
	     }
	}
}


105、无向图最短路径

106、输入一个矩阵,起始点和目标点,判断是否存在可达路径

/**
 * Created by ChaoNi on 2016/9/19.
 */

public class DFS {
    //输入的迷宫矩阵
    private static int[][] matrix= {
            {0,1,0,0,1},
            {0,0,1,1,1},
            {1,0,0,0,0},
            {1,0,1,1,0},
            {1,0,0,0,0},
    };

    //迷宫的宽度
    private static  int width=5;
    //迷宫的高度
    private static int heigth=5;

    //标记迷宫中各个位置是否已经被走过
    private static boolean[][] flag=null;
    //在迷宫中的移动方向
    private static int[][] direction={
            {0,1},
            {0,-1},
            {-1,0},
            {1,0}
    };

    public static void main(String[] args) {
        //起始点
        Point start=new Point(0,0);
        //目标点
        Point end=new Point(width-1,heigth-1);


        flag=new boolean[width][heigth];
        if(existPath(start,end)) System.out.println("yes");
        else System.out.println("no");
       );
   }

    //判断是否存在路径
    public static boolean existPath(Point start,Point end){
        //到达目标点
        if(start.getX()==end.getX()&&start.getY()==end.getY()){
            return true;
        }
        //从四个方向进行再次遍历
        for(int i=0;i<4;i++){
            int nx=start.getX()+direction[i][0];
            int ny=start.getY()+direction[i][1];

            //检验方向的合法性
            if(nx>=0&&nx<width&&ny>=0&&ny<heigth&&flag[nx][ny]==false&&matrix[nx][ny]==0){
                //标记的位置需要对应一下
                flag[nx][ny]=true;
                if(existPath(new Point(nx,ny),end)) return true;
                //当前这个方向不能完成,则回退到前一个结果,进行再次探索
                flag[nx][ny]=false;
            }
        }
        return false;
    }  
}

//位置点的辅助类
class Point {
    private int x;
    private int y;
    public Point(int xx, int yy){
        this.x=xx;
        this.y=yy;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    @Override
    public String toString() {
        return "[" + x +
                ", "+y+"]";
    }
}

leetcode

1. Two Sum:给定数组和target,返回两个元素之和为target的元素index;

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        for (unsigned int i = 0; i < nums.size() - 1; i++)
            for (unsigned int j = i + 1; j < nums.size(); j++)
                if (nums[i] + nums[j] == target)
                return {i,j};
    }
};

public int[] twoSum(int[] nums, int target) {
    for (int i = 0; i < nums.length; i++) {
        for (int j = i + 1; j < nums.length; j++) {
            if (nums[j] == target - nums[i]) {
                return new int[] { i, j };
            }
        }
    }
    throw new IllegalArgumentException("No two sum solution");
}
public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        map.put(nums[i], i);
    }
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (map.containsKey(complement) && map.get(complement) != i) {
            return new int[] { i, map.get(complement) };
        }
    }
    throw new IllegalArgumentException("No two sum solution");
}
public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (map.containsKey(complement)) {
            return new int[] { map.get(complement), i };
        }
        map.put(nums[i], i);
    }
    throw new IllegalArgumentException("No two sum solution");

2. Add Two Numbers:他是一个反转的链表,求真正链表代表数字的和的链表的翻转;

public LinkNode reversal(LinkNode node) {
        LinkNode pro = null; //直接前驱节点
        LinkNode curr = node; //当前结点
        LinkNode next = null; //直接后继节点
        while(curr != null) {
            next = curr.getNext();
            curr.setNext(pro);
            pro = curr;
            curr = next;
        }
        return pro;
    }


链表反转
3. Longest Substring Without Repeating Characters:字符串最长的不重复子序列长度:

public int longestSubStringWithoutDuplication(String str) {
    int curLen = 0;
    int maxLen = 0;
    int[] preIndexs = new int[26];
    Arrays.fill(preIndexs, -1);
    for (int curI = 0; curI < str.length(); curI++) {
        int c = str.charAt(curI) - 'a';
        int preI = preIndexs[c];
        if (preI == -1 || curI - preI > curLen) {
            curLen++;
        } else {
            maxLen = Math.max(maxLen, curLen);
            curLen = curI - preI;
        }
        preIndexs[c] = curI;
    }
    maxLen = Math.max(maxLen, curLen);
    return maxLen;
}

5. Longest Palindromic Substring:字符串最长的回文序列。

string findLongestPalindrome(string &s)
{
	int length=s.size();//字符串长度
	int maxlength=0;//最长回文字符串长度
	int start;//最长回文字符串起始地址
	for(int i=0;i<length;i++)//起始地址
		for(int j=i+1;j<length;j++)//结束地址
		{
			int tmp1,tmp2;
			for(tmp1=i,tmp2=j;tmp1<tmp2;tmp1++,tmp2--)//判断是不是回文
			{
				if(s.at(tmp1)!=s.at(tmp2))
					break;
			}
			if(tmp1>=tmp2&&j-i>maxlength)
			{
				maxlength=j-i+1;
				start=i;
			}
		}
		if(maxlength>0)
			return s.substr(start,maxlength);//求子串
		return NULL;
}
string findLongestPalindrome(string &s)
{
	const int length=s.size();
	int maxlength=0;
	int start;
 
	for(int i=0;i<length;i++)//长度为奇数
	{
		int j=i-1,k=i+1;
		while(j>=0&&k<length&&s.at(j)==s.at(k))
		{
			if(k-j+1>maxlength)
			{
				maxlength=k-j+1;
				start=j;
			}
			j--;
			k++;
		}
	}
 
	for(int i=0;i<length;i++)//长度为偶数
	{
		int j=i,k=i+1;
		while(j>=0&&k<length&&s.at(j)==s.at(k))
		{
			if(k-j+1>maxlength)
			{
				maxlength=k-j+1;
				start=j;
			}
			j--;
			k++;
		}
	}
	if(maxlength>0)
		return s.substr(start,maxlength);
	return NULL;
}
  1. ZigZag Conversion:一个字符串,一个行数。然后字符竖折竖折来排序。然后一层一层的组合字符。

7. Reverse Integer:将整数值反转,如120变21,-21变-12,考虑值超过int溢出。

package TestDemo;
import java.util.*;
public class Test1 {
     public static void main(String[] args){
           Scanner in = new Scanner(System.in);
           int x = in.nextInt();
           int y = reverse(x);
           System.out.println(y);
           in.close();
     }
     
     static int reverse(int x){
           int number = 0;
           while(x != 0){
                int z = x % 10;
                int newnumber = number * 10 + z;
                if((newnumber -z)/ 10 != number ){
                     return 0;                      //在这里因为 int的最大值为2147483647
                }                             // 当 2147483640 + 9/8的时候就发生了溢出
                number = newnumber;
                x = x/10;
           }
           return number;
     }
}

8. String to Integer (atoi):将字符串转化为整数


public class Solution {
    public int StrToInt(String str) {
        if(str==null||str.trim().equals("")){
            return 0;
        }
        char[] cc = str.toCharArray();
        int i,sum=0,flag=1;
        if(cc[0]=='-'){
            i=1;
            flag = -1;
        }
        else if(cc[0]=='+'){
            i=1;
            flag = 1;
        }
        else{
            i=0;
        }
        while(i<cc.length){
            if(isNumber(cc[i])){
                sum = sum * 10 + (cc[i] - '0');
            }
            else{
                return 0;
            }
            i++;
        }
        return sum * flag;
    }
    public boolean isNumber(char c){
        if(c=='0'||c=='1'||c=='2'||c=='3'||c=='4'||c=='5'||c=='6'||c=='7'||c=='8'||c=='9'){
            return true;
        }
        return false;
    }
public int StrToInt(String str) {
    if (str == null || str.length() == 0)
        return 0;
    boolean isNegative = str.charAt(0) == '-';
    int ret = 0;
    for (int i = 0; i < str.length(); i++) {
        char c = str.charAt(i);
        if (i == 0 && (c == '+' || c == '-'))  /* 符号判定 */
            continue;
        if (c < '0' || c > '9')                /* 非法输入 */
            return 0;
        ret = ret * 10 + (c - '0');
    }
    return isNegative ? -ret : ret;
}

9. Palindrome Number,一个数,正反来是否一样。负数不一样。


class Solution {
public:
    bool isPalindrome(int x) {
        int sum=0;
        if(x<0 || (x/10!=0 && x%10==0))
        {
            return false;
        }
        else{
           while(x>sum)
           {
               sum  = sum * 10 + x%10;
               x = x/10;
           }
        }
        /*若整数为偶数*/
        if(sum == x)
        {
            return true;
        }
        /*若整数位数为奇数*/
        if(sum/10 == x)
        {
            return true;
        }
        return false;
    }
};

12. Integer to Roman,给定一个数,转化成罗马数字。

14. Longest Common Prefix;N个字符串,求这N个字符串最长公共前缀


#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
int dp[300][300][300];
char a[1000];
char b[1000];
char c[1000];
int main()
{
    memset(dp,0,sizeof(0));
    gets(a);
    gets(b);
    gets(c);
    int lena=strlen(a);
    int lenb=strlen(b);
    int lenc=strlen(c);
    for(int i=1;i<=lena;i++)
    {
        for(int j=1;j<=lenb;j++)
        {
            for(int k=1;k<=lenc;k++)
            {
                if(a[i-1]==b[j-1]&&a[i-1]==c[k-1])
                {
                    dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][k-1]+1);
                }
                else
                    dp[i][j][k]=max(max(dp[i-1][j][k],dp[i][j-1][k]),dp[i][j][k-1]);
            }
        }
    }
    printf("%d\n",dp[lena][lenb][lenc]);
    return 0;
}

15. 3Sum,数组中,找3个和为0为三个数,每个数不能用两次。要考虑重复的问题。

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> res;
        sort(nums.begin(), nums.end());
        if (nums.empty() || nums.back() < 0 || nums.front() > 0) return {};
        for (int k = 0; k < (int)nums.size() - 2; ++k) {
            if (nums[k] > 0) break;
            if (k > 0 && nums[k] == nums[k - 1]) continue;
            int target = 0 - nums[k], i = k + 1, j = (int)nums.size() - 1;
            while (i < j) {
                if (nums[i] + nums[j] == target) {
                    res.push_back({nums[k], nums[i], nums[j]});
                    while (i < j && nums[i] == nums[i + 1]) ++i;
                    while (i < j && nums[j] == nums[j - 1]) --j;
                    ++i; --j;
                } else if (nums[i] + nums[j] < target) ++i;
                else --j;
            }
        }
        return res;
    }
};

16. 3Sum Closest:一个数组,找出3个和最进阶target的。

17. Letter Combinations of a Phone Number,给定数字,求九宫格拼音下的所有组合。回溯

18. 4Sum.数组中4个数之和为0,考虑重复的数.

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> result;
        int length = nums.size();
        if(length < 4)
            return result;
        sort(nums.begin(), nums.end());
        for(int i = 0; i < length - 3; i++){
            if(i != 0 && nums[i] == nums[i-1])
                continue;
            for(int j = i+1; j < length - 2; j++){
                if(j != i+1 && nums[j] == nums[j-1])
                    continue;
                int L = j + 1;
                int R = length - 1;
                while(L < R){
                    if(L != j+1 && nums[L] == nums[L-1]){
                        L++;
                        continue;
                    }

                    if(R != length -1 && nums[R] == nums[R+1]){
                        R--;
                        continue;
                    }

                    int sum = nums[i] + nums[j] + nums[L] + nums[R];
                    if(sum == target){
                        result.push_back({nums[i], nums[j], nums[L], nums[R]});
                        L++;
                        R--;
                    }
                    else if(sum > target)
                        R--;
                    else
                        L++;
                } 
            }
        }
        return result;
    }

};

19,删除倒数第k个节点

public ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode fast = head;
    while (n-- > 0) {
        fast = fast.next;
    }
    if (fast == null) return head.next;
    ListNode slow = head;
    while (fast.next != null) {
        fast = fast.next;
        slow = slow.next;
    }
    slow.next = slow.next.next;
    return head;
}

20、括号序列是否匹配:

public boolean isValid(String s) {
    Stack<Character> stack = new Stack<>();
    for (char c : s.toCharArray()) {
        if (c == '(' || c == '{' || c == '[') {
            stack.push(c);
        } else {
            if (stack.isEmpty()) {
                return false;
            }
            char cStack = stack.pop();
            boolean b1 = c == ')' && cStack != '(';
            boolean b2 = c == ']' && cStack != '[';
            boolean b3 = c == '}' && cStack != '{';
            if (b1 || b2 || b3) {
                return false;
            }
        }
    }
    return stack.isEmpty();
}

21、合并两个有序链表,递归和非递归方式。

public ListNode Merge(ListNode list1, ListNode list2) {
    if (list1 == null)
        return list2;
    if (list2 == null)
        return list1;
    if (list1.val <= list2.val) {
        list1.next = Merge(list1.next, list2);
        return list1;
    } else {
        list2.next = Merge(list1, list2.next);
        return list2;
    }
}
public class MergeTwoList {
    public static ListNode mergeTwoLst(ListNode head1,ListNode head2){
        // 处理异常情况
        if(head1 == null)  return head1;

        if(head2 == null)  return head1;
        
        // 新链表的dummyHead,初始值随意
        ListNode dummyHead = new ListNode(-1);
        ListNode cur = dummyHead;
        ListNode cur1 = head1;
        ListNode cur2 = head2;
        // 遍历
        while(cur1 != null && cur2 != null){
            if(cur1.val <= cur2.val){
                cur.next = cur1;
                cur1 = cur1.next;
            }else{    // cur1.val > cur2.val
                cur.next = cur2;
                cur2 = cur2.next;
            }
            cur = cur.next;
        }
        // 一个链表已经遍历完毕
       if(cur1 != null){
            cur.next = cur1;
       }else{
            cur.next = cur2;
       }
        return dummyHead.next;
    }
}

22、n对小括号的全正确排序:回溯

24. 成对的翻转链表

public ListNode swapPairs(ListNode head) {
    ListNode node = new ListNode(-1);
    node.next = head;
    ListNode pre = node;
    while (pre.next != null && pre.next.next != null) {
        ListNode l1 = pre.next, l2 = pre.next.next;
        ListNode next = l2.next;
        l1.next = next;
        l2.next = l1;
        pre.next = l2;

        pre = l1;
    }
    return node.next;
}

26、有序数组,删除多余的重复数组,in-place删除,然后返回长度。


int remove(int *arr, int sz)
{
	int i = 0;
	int index = 0;
 
	for (i = 1; i < sz; i++) {
		if (arr[index] != arr[i]) {	//依次向后比较,若不相等,则用arr[i]覆盖arr[index+1],否则(遇到的是重复元素),i往后移
			arr[++index] = arr[i];	//当index与i之间没有其他元素,index + 1 就是i哦,相当于index后移,但是值没改变
		}				//当index与i之间有其他元素,那么这些元素必定是重复得了,直接覆盖掉
	}
 
	return index + 1;

27、数组,删除指定的数字;

    int removeElement(int A[], int n, int elem) {
        int index=0;
        for(int i=0;i<n;i++){
            if(A[i]!=elem){
                A[index++]=A[i];
            }
        }
        return index;
    }

28、实现indexOf(String s1,String s2);

33、左移一部分的有序数组中,查询target。二分查找的经典题目

    public int search(int[] arr, int key){
        if(arr.length == 0){
            return -1;
        }
        int left = 0;
        int right = arr.length - 1;

        while (left < right){
            int mid = left + (right - left)/2;
            if (arr[mid] == key){
                return mid;
            }
            //如果前半段有序
            if (arr[mid] > arr[left]){
                //判断Key是否在前半段,如果在,则继续遍历前半段;如果不在,则遍历后半段
                if (arr[mid] > key){
                    right = mid - 1;
                }else {
                    left = mid + 1;
                }
            }
            //如果后半段有序
            if (arr[mid] < arr[right]){
                //判断Key是否在后半段,如果在,则继续遍历后半段;如果不在,则遍历前半段
                if (arr[mid] < key){
                    left = mid + 1;
                }else {
                    right = mid - 1;
                }
            }
        }
        return  -1;
    }

**34、有序数组中,查询一个target第一次和最后一次出现的位置;二分查找的经典题目
**

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int a = search(nums,target);
        int b = search(nums,target+1);
        if(a==nums.length||nums[a]!=target)
            return new int[]{-1,-1};
        return new int[]{a,b-1};
    }
    
    int search(int[] nums, int t) {
        int l = 0,r = nums.length;
        while(l<r){
            int m = (l+r)>>>1;
            if(nums[m]<t)
                l = m+1;
            else
                r = m;
        }
        return l;
    }
}
class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] targetRange = {-1, -1};

        // find the index of the leftmost appearance of `target`.
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == target) {
                targetRange[0] = i;
                break;
            }
        }

        // if the last loop did not find any index, then there is no valid range
        // and we return [-1, -1].
        if (targetRange[0] == -1) {
            return targetRange;
        }

        // find the index of the rightmost appearance of `target` (by reverse
        // iteration). it is guaranteed to appear.
        for (int j = nums.length-1; j >= 0; j--) {
            if (nums[j] == target) {
                targetRange[1] = j;
                break;
            }
        }

        return targetRange;
    }
}

35、将一个数插入到有序数组中,求位置

package com.array.test;

import java.util.Arrays;
import java.util.Scanner;

/**
 * 实现:在有序数组中插入一个元素,保持数组仍然有序
 * 对新数组排序---1)找要插入的位置
 *               2)将该位置后面的数据,都往后挪一位
 *               3)把新数据插到该位置
 */
public class ArrayInsertThree {
    public static void main(String[] args) {
        int[] arr=new int[]{5,8,19,20,23};
        System.out.println("原数组为:arr="+ Arrays.toString(arr));
        Scanner sc=new Scanner(System.in);
        System.out.println("请输入插入的数据");
        int number=sc.nextInt();   //要插入的数据
        int index=arr.length-1; //用来保存要插入的位置,默认是数组最后一个位置

        //1、遍历数组,找到要插入的位置
        for(int i=0;i<arr.length-1;i++){
            if(arr[i]>number){
                index=i;                    //一旦数组元素大于number,说明这个位置就是要插入的位置
                break;                     //记下该位置,退出循环
            }
        }

        //2、将后面的数据向后挪,处理index后面的数据
        for(int i=arr.length-1;i>index;i--){    //要倒着赋值
            arr[i]=arr[i-1];
        }

        //3、把数据插入到指定位置
        arr[index]=number;

        System.out.println(Arrays.toString(arr));

    }
}


39:非重复数组,找出和为target的数组,一个不能用两次;回溯。

public int[] twoSum(int[] nums, int target) {
       int[] result = new int[2];
       for(int i = 0; i < nums.length; i++) {
           for(int j = i + 1; j < nums.length; j++) {
               if(nums[i] + nums[j] == target) {
                   result[0] = i;
                   result[1] = j;
                   return result;
               }
           }
       }
       return result;
}

40,带有重复的数组,找出和未target的数组组合,一个不能用两次;回溯+组合

43,两字符串的数字,相乘,得到结果,输出字符串。

46,不重复数组的,所有全排列;回溯+排列

public List<List<Integer>> permute(int[] nums) {
    List<List<Integer>> permutes = new ArrayList<>();
    List<Integer> permuteList = new ArrayList<>();
    boolean[] hasVisited = new boolean[nums.length];
    backtracking(permuteList, permutes, hasVisited, nums);
    return permutes;
}

private void backtracking(List<Integer> permuteList, List<List<Integer>> permutes, boolean[] visited, final int[] nums) {
    if (permuteList.size() == nums.length) {
        permutes.add(new ArrayList<>(permuteList)); // 重新构造一个 List
        return;
    }
    for (int i = 0; i < visited.length; i++) {
        if (visited[i]) {
            continue;
        }
        visited[i] = true;
        permuteList.add(nums[i]);
        backtracking(permuteList, permutes, visited, nums);
        permuteList.remove(permuteList.size() - 1);
        visited[i] = false;
    }
}

47,带有重复的数组,全排列;回溯+排列+去重

public List<List<Integer>> permuteUnique(int[] nums) {
    List<List<Integer>> permutes = new ArrayList<>();
    List<Integer> permuteList = new ArrayList<>();
    Arrays.sort(nums);  // 排序
    boolean[] hasVisited = new boolean[nums.length];
    backtracking(permuteList, permutes, hasVisited, nums);
    return permutes;
}

private void backtracking(List<Integer> permuteList, List<List<Integer>> permutes, boolean[] visited, final int[] nums) {
    if (permuteList.size() == nums.length) {
        permutes.add(new ArrayList<>(permuteList));
        return;
    }

    for (int i = 0; i < visited.length; i++) {
        if (i != 0 && nums[i] == nums[i - 1] && !visited[i - 1]) {
            continue;  // 防止重复
        }
        if (visited[i]){
            continue;
        }
        visited[i] = true;
        permuteList.add(nums[i]);
        backtracking(permuteList, permutes, visited, nums);
        permuteList.remove(permuteList.size() - 1);
        visited[i] = false;
    }
}

48:n x n矩阵,顺时针转动90度。

49,一群字符串,有些字符串字母组成一样,有的不一样,将一样的放一块;

50:计算power(x,n); x在正负100,n在正负 2^31;

class Solution {
public:
    double fastPow(double x, long long n) {
        if (n == 0) {
            return 1.0;
        }
        double half = fastPow(x, n / 2);
        if (n % 2 == 0) {
            return half * half;
        } else {
            return half * half * x;
        }
    }
    double myPow(double x, int n) {
        long long N = n;
        if (N < 0) {
            x = 1 / x;
            N = -N;
        }
        return fastPow(x, N);
    }
};

54:一圈圈顺时针打印数组。

public ArrayList<Integer> printMatrix(int[][] matrix) {
    ArrayList<Integer> ret = new ArrayList<>();
    int r1 = 0, r2 = matrix.length - 1, c1 = 0, c2 = matrix[0].length - 1;
    while (r1 <= r2 && c1 <= c2) {
        for (int i = c1; i <= c2; i++)
            ret.add(matrix[r1][i]);
        for (int i = r1 + 1; i <= r2; i++)
            ret.add(matrix[i][c2]);
        if (r1 != r2)
            for (int i = c2 - 1; i >= c1; i--)
                ret.add(matrix[r2][i]);
        if (c1 != c2)
            for (int i = r2 - 1; i > r1; i--)
                ret.add(matrix[i][c1]);
        r1++; r2--; c1++; c2--;
    }
    return ret;
}

58:最后一个单词的长度。

import java.io.Console;
import java.util.Scanner;
 
public class Main {
 
	public static void main(String[] args) {		
        //控制台输入
		Scanner scanner = new Scanner(System.in);
		String st = scanner.nextLine();
 
	    int n = getLastStringNum(st);
		System.out.println(n);
	}
 
	public static int getLastStringNum(String st){
		int n = 0;
		if(st != null){
			String[] s = st.split(" ");
			String string = s[s.length-1];
			n = string.length();
		}		
		return n;
	}
	
}

59:给一个N,将1-N^2,整成上面外圈顺时针到里圈的矩阵。

60:1-N这n个数字的全排列,求第K小的;

61、翻转链表,链表右移K为,可以循环多移;

public ListNode rotateRight(ListNode head, int k) {

        if (head == null || k == 0) {
            return head;
        }
        ListNode tmp = head;
        int len = 0;
        //求出链表的长度
        while (tmp != null) {
            tmp = tmp.next;
            len++;
        }
        k = k % len;  //以len为一个周期
        if (k == 0) {
            return head;
        }
        //保存一下头节点
        ListNode node = head;
        //快慢指针
        tmp = head;
        while (k > 0) {
            k--;
            tmp = tmp.next;
        }
        while (tmp.next != null) {
            head = head.next;
            tmp = tmp.next;
        }
        //记录next的位置,也就是返回值的头结点
        ListNode res = head.next;
        //断开连接
        head.next = null;
        //后一段的末尾指向前一段的开头
        tmp.next = node;
        return res;

    }

62、矩阵移动,mxn矩阵从左上角移动到右下角,只能横移和竖移,共有多少方法;


int sum(int m, int n)//非递归
{
	int ** a = (int**)calloc(m, sizeof(int*));
	for (int i = 0; i < m; i++)
	{
		a[i] = (int*)calloc(n, sizeof(int));
	}
	for (int i = 0; i < m; i++)
	{
		a[i][0] = 1;//第一列赋值为1
		a[0][i] = 1;
	}
	//int t;
	for (int i = 1; i < m; i++)
	{
		for (int j = 1; j < n; j++)
		{
			a[i][j] = a[i - 1][j] + a[i][j - 1];
		//	t = a[i][j];
			//int c=t;
		}
	}
	
	return a[m-1][n-1];
import java.util.*;
 
public class Zuoye9 {
 
	public static void main(String[] args) {
 
		Scanner reader = new Scanner(System.in);
		int mytwo[][] = new int[1000][1000];
 
		System.out.println("输入M X N的网格值");
 
		System.out.println("n=");
		int n=reader.nextInt();
 
		System.out.println("m=");
		int m=reader.nextInt();          //nxm阶矩阵
 
		for(int i=0;i<m;i++) {           //(0,m)赋值,给mytwo[0][i]赋值
			mytwo[0][i] = 1;
		}
 
		for(int i=0;i<n;i++) {          //(n,0)赋值,给mytwo[i][0]赋值
			mytwo[i][0] = 1;
		}
 
		for(int i=1;i<n;i++) {
			for(int j=1;j<m;j++) {
				mytwo[i][j] = mytwo[i-1][j] + mytwo[i][j-1];
			}
		}
 
		System.out.println(mytwo[n-1][m-1]);
	}
 
}

63、矩阵移动,从左上移动到右下:横竖移动,矩阵值为1的不能走;求多少种移动方式。

64、矩阵,从左上到右下,最短的路径和多少。

import java.util.Scanner;
 
public class MaxMatrixPath {
	public static int getMaxPathSum(int[][] nums) {
		if(nums == null || nums.length == 0)
			return 0;
		int M = nums.length;
		int N = nums[0].length;
		int dp[][] = new int[M][N];
		for(int j = 0; j < N; j++) {
			for(int i = 0; i < M; i++) {
				if(i == 0 && j == 0) {
					dp[i][j] = nums[i][j];
					continue;
				}
				if(j == 0) {
					dp[i][j] = dp[i-1][j] + nums[i][j];
					continue;
				}
				if(i == 0) {
					dp[i][j] = dp[i][j-1] + nums[i][j];
					continue;
				}
				dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]) + nums[i][j];
			}
		}
		return dp[M-1][N-1];
	}
 
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()) {
			int M = sc.nextInt();
			int N = sc.nextInt();
			int[][] nums = new int[M][N];
			for(int i = 0; i < M; i++) {
				for(int j = 0; j < N; j++) {
					nums[i][j] = sc.nextInt();
				}
			}
			System.out.println(getMaxPathSum(nums));
		}
		sc.close();
	}
}

66、数组表示的数+1,然后返回之后的。

67、两个二进制字符串相加,得到的二进制字符串。

public String addBinary(String a, String b) {
    int i = a.length() - 1, j = b.length() - 1, carry = 0;
    StringBuilder str = new StringBuilder();
    while (carry == 1 || i >= 0 || j >= 0) {
        if (i >= 0 && a.charAt(i--) == '1') {
            carry++;
        }
        if (j >= 0 && b.charAt(j--) == '1') {
            carry++;
        }
        str.append(carry % 2);
        carry /= 2;
    }
    return str.reverse().toString();
}

69. Sqrt(x) 实现int sqrt(int x);

public int mySqrt(int x) {
    if (x <= 1) {
        return x;
    }
    int l = 1, h = x;
    while (l <= h) {
        int mid = l + (h - l) / 2;
        int sqrt = x / mid;
        if (sqrt == mid) {
            return mid;
        } else if (mid > sqrt) {
            h = mid - 1;
        } else {
            l = mid + 1;
        }
    }
    return h;
}

73、MxN的数组,如果有一个为0,那么就让起其所有列和行都为0,求最后的数组;

74、mxn的矩阵,层序遍历就是有序的数组。在矩阵中搜索target;

public boolean searchMatrix(int[][] matrix, int target) {
    if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false;
    int m = matrix.length, n = matrix[0].length;
    int row = 0, col = n - 1;
    while (row < m && col >= 0) {
        if (target == matrix[row][col]) return true;
        else if (target < matrix[row][col]) col--;
        else row++;
    }
    return false;
}

75:一个只有2、1、0的数组,将0分到左边,2移动右边。

77:1-N,挑选K个进行排列;

78:求数组的所有子集合。

public List<List<Integer>> subsets(int[] nums) {
    List<List<Integer>> subsets = new ArrayList<>();
    List<Integer> tempSubset = new ArrayList<>();
    for (int size = 0; size <= nums.length; size++) {
        backtracking(0, tempSubset, subsets, size, nums); // 不同的子集大小
    }
    return subsets;
}

private void backtracking(int start, List<Integer> tempSubset, List<List<Integer>> subsets,
                          final int size, final int[] nums) {

    if (tempSubset.size() == size) {
        subsets.add(new ArrayList<>(tempSubset));
        return;
    }
    for (int i = start; i < nums.length; i++) {
        tempSubset.add(nums[i]);
        backtracking(i + 1, tempSubset, subsets, size, nums);
        tempSubset.remove(tempSubset.size() - 1);
    }
}

80:删除有序数组中过于多余的数字,最多每个出现两次。
81 删除有序数组中重复的数字

class Solution {
    public int removeDuplicates(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int back = 0;
        for (int front = 1; front < nums.length; front++) {
            if (nums[back] != nums[front]) {
                back++;
                nums[back] = nums[front];
            }
        }
        return back + 1;
    }
}

81:翻转部分的有序数组,可能存在重复,搜索target;

82:删除有序链表,将重复的全都删了;

83:删除有序链表多余的节点,重复的保留一个。

public ListNode deleteDuplicates(ListNode head) {
    if (head == null || head.next == null) return head;
    head.next = deleteDuplicates(head.next);
    return head.val == head.next.val ? head.next : head;
}

86:链表,给定target,将比target小的节点移动到左边。大的和等于的移动到后面。其他相对位置不变。

ListNode* partition(ListNode* pHead, int x)
    {
        struct ListNode* lhead ,*ltail;
        struct ListNode* ghead,*gtail;
        struct ListNode* cur = pHead;
        ltail = lhead = (struct ListNode*)malloc(sizeof(struct ListNode));
        gtail = ghead = (struct ListNode*)malloc(sizeof(struct ListNode));
        //遍历每一个元素
        while(cur)
        {
            //判断当前元素是否小于x
            if(cur->val < x)
            {
                ltail->next = cur;
                ltail = ltail->next;
            }
            else
            {
                gtail->next = cur;
                gtail = gtail->next;
            }
            cur = cur->next;
        }
        //连接两个新的链表
        ltail->next = ghead->next;
        //链表最后一个为NULL
        gtail->next = NULL;
        pHead = lhead->next;
        free(lhead);
        free(ghead);
        return pHead;
    }

88:将两个有序数组合到第一个数组中;

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int len1 = m - 1;
        int len2 = n - 1;
        int len = m + n - 1;
        while(len1 >= 0 && len2 >= 0) {
            // 注意--符号在后面,表示先进行计算再减1,这种缩写缩短了代码
            nums1[len--] = nums1[len1] > nums2[len2] ? nums1[len1--] : nums2[len2--];
        }
        // 表示将nums2数组从下标0位置开始,拷贝到nums1数组中,从下标0位置开始,长度为len2+1
        System.arraycopy(nums2, 0, nums1, 0, len2 + 1);
    }
}

90:可能有重复元素的数组,求所有的组合。

public List<List<Integer>> combinationSum2(int[] candidates, int target) {
    List<List<Integer>> combinations = new ArrayList<>();
    Arrays.sort(candidates);
    backtracking(new ArrayList<>(), combinations, new boolean[candidates.length], 0, target, candidates);
    return combinations;
}

private void backtracking(List<Integer> tempCombination, List<List<Integer>> combinations,
                          boolean[] hasVisited, int start, int target, final int[] candidates) {

    if (target == 0) {
        combinations.add(new ArrayList<>(tempCombination));
        return;
    }
    for (int i = start; i < candidates.length; i++) {
        if (i != 0 && candidates[i] == candidates[i - 1] && !hasVisited[i - 1]) {
            continue;
        }
        if (candidates[i] <= target) {
            tempCombination.add(candidates[i]);
            hasVisited[i] = true;
            backtracking(tempCombination, combinations, hasVisited, i + 1, target - candidates[i], candidates);
            hasVisited[i] = false;
            tempCombination.remove(tempCombination.size() - 1);
        }
    }
}

91:将数字解码成A-Z;1-26;给出数字字符串,有几种解码方式:

public int numDecodings(String s) {
    if (s == null || s.length() == 0)
        return 0;
    int n = s.length();
    int[] dp = new int[n + 1];
    dp[0] = 1;
    dp[1] = s.charAt(0) == '0' ? 0 : 1;
    for (int i = 2; i <= n; i++) {
        int one = Integer.valueOf(s.substring(i - 1, i));
        if (one != 0)
            dp[i] += dp[i - 1];
        if (s.charAt(i - 2) == '0')
            continue;
        int two = Integer.valueOf(s.substring(i - 2, i));
        if (two <= 26)
            dp[i] += dp[i - 2];
    }
    return dp[n];
}

92:逆转链表的m-n这部分;

93:给定一数字字符串,输出可能的IP地址列表。

public List<String> restoreIpAddresses(String s) {
        List<String> result = new ArrayList<>();
        StringBuilder ip = new StringBuilder();

        for (int a = 1; a < 4; a++) {
            for (int b = 1; b < 4; b++) {
                for (int c = 1; c < 4; c++) {
                    for (int d = 1; d < 4; d++) {
                        /*
                         * 1、保障下面subString不会越界
                         * 2、保障截取的字符串与输入字符串长度相同
                         * //1、2比较好理解,3比较有意思
                         * 3、不能保障截取的字符串转成int后与输入字符串长度相同
                         * 如:字符串010010,a=1,b=1,c=1,d=3,对应字符串0,1,0,010
                         * 转成int后seg1=0,seg2=1,seg3=0,seg4=10
                         * //所以需要下面这处判断if (ip.length() == s.length() + 3)
                         */
                        if (a + b + c + d == s.length()) {
                            int seg1 = Integer.parseInt(s.substring(0, a));
                            int seg2 = Integer.parseInt(s.substring(a, a + b));
                            int seg3 = Integer.parseInt(s.substring(a + b, a + b + c));
                            int seg4 = Integer.parseInt(s.substring(a + b + c, a + b + c + d));
                            // 四个段数值满足0~255
                            if (seg1 <= 255 && seg2 <= 255 && seg3 <= 255 && seg4 <= 255) {
                                ip.append(seg1).append(".").append(seg2).append(".").
                                        append(seg3).append(".").append(seg4);
                                // 保障截取的字符串转成int后与输入字符串长度相同
                                if (ip.length() == s.length() + 3) {
                                    result.add(ip.toString());
                                }
                                ip.delete(0, ip.length());
                            }
                        }
                    }
                }
            }
        }
        return result;
    }

94,二叉树中序遍历:

public List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> ret = new ArrayList<>();
    if (root == null) return ret;
    Stack<TreeNode> stack = new Stack<>();
    TreeNode cur = root;
    while (cur != null || !stack.isEmpty()) {
        while (cur != null) {
            stack.push(cur);
            cur = cur.left;
        }
        TreeNode node = stack.pop();
        ret.add(node.val);
        cur = node.right;
    }
    return ret;
}

96:n个节点,共有多少种二叉搜索树。

public List<TreeNode> generateTrees(int n) {
    if (n < 1) {
        return new LinkedList<TreeNode>();
    }
    return generateSubtrees(1, n);
}

private List<TreeNode> generateSubtrees(int s, int e) {
    List<TreeNode> res = new LinkedList<TreeNode>();
    if (s > e) {
        res.add(null);
        return res;
    }
    for (int i = s; i <= e; ++i) {
        List<TreeNode> leftSubtrees = generateSubtrees(s, i - 1);
        List<TreeNode> rightSubtrees = generateSubtrees(i + 1, e);
        for (TreeNode left : leftSubtrees) {
            for (TreeNode right : rightSubtrees) {
                TreeNode root = new TreeNode(i);
                root.left = left;
                root.right = right;
                res.add(root);
            }
        }
    }
    return res;
}

98:判断一个树,是否是二叉搜索树。

100:判断两个树是否一致。

101:判断一个树是否对称。

public boolean isSymmetric(TreeNode root) {
    if (root == null) return true;
    return isSymmetric(root.left, root.right);
}

private boolean isSymmetric(TreeNode t1, TreeNode t2) {
    if (t1 == null && t2 == null) return true;
    if (t1 == null || t2 == null) return false;
    if (t1.val != t2.val) return false;
    return isSymmetric(t1.left, t2.right) && isSymmetric(t1.right, t2.left);
}

102:二叉树层序遍历。

public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
    Queue<TreeNode> queue = new LinkedList<>();
    ArrayList<Integer> ret = new ArrayList<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        int cnt = queue.size();
        while (cnt-- > 0) {
            TreeNode t = queue.poll();
            if (t == null)
                continue;
            ret.add(t.val);
            queue.add(t.left);
            queue.add(t.right);
        }
    }
    return ret;
}

103,之字形打印二叉树

public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
    ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
    Queue<TreeNode> queue = new LinkedList<>();
    queue.add(pRoot);
    boolean reverse = false;
    while (!queue.isEmpty()) {
        ArrayList<Integer> list = new ArrayList<>();
        int cnt = queue.size();
        while (cnt-- > 0) {
            TreeNode node = queue.poll();
            if (node == null)
                continue;
            list.add(node.val);
            queue.add(node.left);
            queue.add(node.right);
        }
        if (reverse)
            Collections.reverse(list);
        reverse = !reverse;
        if (list.size() != 0)
            ret.add(list);
    }
    return ret;
}

104:二叉树的深度:

public int maxDepth(TreeNode root) {
    if (root == null) return 0;
    return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}

105:前序和中序构成二叉树。

106:中序和后序构成二叉树

107:层序遍历:从底层到上层;

public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
    Queue<TreeNode> queue = new LinkedList<>();
    ArrayList<Integer> ret = new ArrayList<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        int cnt = queue.size();
        while (cnt-- > 0) {
            TreeNode t = queue.poll();
            if (t == null)
                continue;
            ret.add(t.val);
            queue.add(t.left);
            queue.add(t.right);
        }
    }
    return ret;
}

108: 将有序数组转化成二叉搜索树

public TreeNode sortedArrayToBST(int[] nums) {
    return toBST(nums, 0, nums.length - 1);
}

private TreeNode toBST(int[] nums, int sIdx, int eIdx){
    if (sIdx > eIdx) return null;
    int mIdx = (sIdx + eIdx) / 2;
    TreeNode root = new TreeNode(nums[mIdx]);
    root.left =  toBST(nums, sIdx, mIdx - 1);
    root.right = toBST(nums, mIdx + 1, eIdx);
    return root;
}

109:将有序链表转化成二叉搜索树:

public TreeNode sortedListToBST(ListNode head) {
    if (head == null) return null;
    if (head.next == null) return new TreeNode(head.val);
    ListNode preMid = preMid(head);
    ListNode mid = preMid.next;
    preMid.next = null;  // 断开链表
    TreeNode t = new TreeNode(mid.val);
    t.left = sortedListToBST(head);
    t.right = sortedListToBST(mid.next);
    return t;
}

private ListNode preMid(ListNode head) {
    ListNode slow = head, fast = head.next;
    ListNode pre = head;
    while (fast != null && fast.next != null) {
        pre = slow;
        slow = slow.next;
        fast = fast.next.next;
    }
    return pre;
}

110:是否平衡二叉树:

private boolean result = true;

public boolean isBalanced(TreeNode root) {
    maxDepth(root);
    return result;
}

public int maxDepth(TreeNode root) {
    if (root == null) return 0;
    int l = maxDepth(root.left);
    int r = maxDepth(root.right);
    if (Math.abs(l - r) > 1) result = false;
    return 1 + Math.max(l, r);
}

111:叶节点到根节点的最短路径。

112:二叉树是否存在从根节点到叶节点的路径和为target:

public boolean hasPathSum(TreeNode root, int sum) {
    if (root == null) return false;
    if (root.left == null && root.right == null && root.val == sum) return true;
    return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
}

113:找出所有路径和为target的序列

114:将二叉树往一边偏;

116:满二叉树,将为每个节点加上next,就是每层的右边那个。

117:二叉树,将为每个节点加上next,就是每层的右边那个。

125:字符串是否回文,只考虑数字和字母,大小写不论。

129:二叉树,从头结点到尾节点:拼接成数字,然后所有的加一块。

136,一个数组,一个出现一次,其他的出现两次,求一次的那个

137:数组,有人出现三次,有人出现一次,求一次的。

138:带有random指针的复杂链表的复制:

141. 链表是否有环:

142:链表环入口节点

143:重排链表:1-2-3-4-5;先第一,再最后一个,先第二个,再倒二,就这样。

144:前序遍历二叉树:

146. LRU Cache

147:对链表进行插入排序,

148:NlongN的时间排序链表。

150、逆波兰

151、单词逆序:

155、带有最小值函数的栈

160:两个链表的相交点

165:比较版本号大小。如10.2.2大于3.1.2;

167:有序数组,找出两数之和为target的索引。

168:数字转化为26进制的A-Z;

169. Majority Element,超过一半的数字

171:26进制A-Z转化为十进制数字

172:Given an integer n, return the number of trailing zeroes in n!.

179:整数数组,求组合到一块的最大值。

189:数组左移K位

199:二叉树,从右边看到的节点数组。也就是每层最右边那个。

200:dfs求岛屿的个数。1表示陆地,0表示岛屿。

201:N-M数组的连续数,逐个&;求最后的结果。

209 : 最短的连续子序列之和大于等于target;

215:无序数组中找出最K大的数字:

216:1-9的数,选出n个,之和为k。求所有N的组合,一个数不能用两次

220:一个数组,是否存在不同的数i和j,使得nums[i]-nums[j]的绝对值最大是t,而i-j的绝对值最大是k;

221:矩阵,有0有1;找出最大的正方形,其里面数值都1;

222:给定一完全二叉树,求节点总个数。

223:以(A,B)和(C,D)为对角顶点,构建矩形,以EF,GH构建,求纵的矩形面积。

227:非负整数,有±*/和空格数字的字符串组成的表达式,求表达式的值;

228:给出排序好的数组,没有重复,将连续的整成0->2的形式,求所有的连续范围段。

229,数组中超过n/3的次数的数。

230:BST二叉搜索树中,第K小的节点,递归和非递归方式

236:二叉树中,两个节点最近的公共祖先节点。

238:构建乘积数组

240:在矩阵中遍历,每行都增加,每列都增加。

241:数字和操作符,±*,请随便加括号改变计算顺序,然后得出所有可能的结果。

260:数组,只有两个出线一次,其他的出现两次,求出现一次的那俩

264:第K个丑数,因子只有2,3,5的数;

274:if h of his/her N papers have at least h citations each, and the other N − h papers have no more than h citations each.

275:同上,也是求H。但这个数组是有序的;

287:N+1数,都是1-n之间,求重复的那个数。

300:最长递增序列,可以不连续。但是前面的index比后面的小

306:数字字符串,我们将字符串分割最少三个数字,然后Fn = Fn-1+Fn-2;

313:求第N个超级丑数,并且给出数组因子,只有只包括该数组因子的数才是超级丑数

318: 字符串数组,求两个没有公共字母的字符串长度乘积的最大值;

319:开关转换,刚开始有N的灯,最初都是灭的,第一轮,每一个都按一个。第二轮每二个按一个开关。第N轮之后,亮着的灯的个数

322:给一堆零钱,可以重复使用,然后给整钱。将整钱换成零钱,求最小的零钱数,如果不能换,返回-1;

324:无序数组重排序:nums[0] < nums[1] > nums[2] < nums[3]…

328:链表重排序,将奇数位index,而不是奇数值的放到前面。偶数index的放后面:

331:将一个二叉树,他的空子节点记成#,给定一个字符串,问这个是不是前序遍历;

332 : 航班信息[from,to],一些列的这种数组信息,这人从JFK出发,求他的真正路线一次经过的城市;

334:数字数组,是否存在三个子序列,可以不连续,是递增的;

338:给定一num.求0-num这些数每个的二进制中1的个数。

347,TopK出现频率最高的数字,一个数组,每个数字可能出现多次,求最K多出现的那k个

343:给定一个整数,将他分成最小二段,和为这个整数,求这些段乘积的最大值。

357:n位数的数,求没有重复数字的总个数。11,121这种就不行。

算法思想
双指针
1.有序数组的TWOSUM
2.两数平方和
3.反转字符数组的元音字符
4.回文字符串
5.归并两个有序数组
6,判断链表是否存在环
7.最长子序列

排序
1.快速排序
2.堆
(1)Kth Element
3.桶排序
(1)出现频率最多的K个元素
(2)按照字符出现的次数对字符串排序
4.荷兰国旗问题
(1)按颜色进行排序
贪心思想
在这里插入图片描述

二分查找
在这里插入图片描述
分治

搜索
在这里插入图片描述
在这里插入图片描述
动态规划
在这里插入图片描述
在这里插入图片描述
数学
在这里插入图片描述


数据结构相关
链表
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
栈和队列
在这里插入图片描述
哈希表
在这里插入图片描述
字符串
在这里插入图片描述
数组和矩阵
在这里插入图片描述

在这里插入图片描述
位运算
在这里插入图片描述

1.最小堆;
2.大数据归并排序、遗传算法 sqrt()是实现,归并排序实现,mapreduce 排序
3.快速排序和堆排序的优缺点,为什么?
4.一个是链表相加,思路就是反转 然后求和,另一个是多个有序数组 归并,用优先队列就好
5.最后一个算法题,是一个装水的问题,问在装多少,我用的双指针
6.LintCode -最小子串覆盖
7.查找数组中的最小元素 二分
8.第二题是算两个没有公共字母的字符串的最大长度积
9.LintCode - 反转二叉树
10.LintCode - 翻转字符串
11.单链表的快速排序
12.LintCode - 接雨水 III,写具体的方法和算法
13.整数去重问题
14.找出增序排列中一个数字第一次和最后一次出现的数组下标
15.海量数据去重
16.找出海量数据中前 10 个最大的数(数据有重复)
17.数组先升序在降序,找出最大数
18.正整数数组,拼出一个最大的正数
19.一个正整数数组,给其中一个数字加 1,使得所有数乘积最大,找出加 1 的那个数字
20.手写快排、堆排 二分查找
21.单词接龙的程序
22.括号匹配;
23.一个数组存着负数与正数,将正数放在前年,负数放在后面
24.母鸡、公鸡和小鸡问题:公鸡五块一只,母鸡三块一只,小鸡一块三只,用 100 元买 100只鸡的
25.各种排序算法的时间复杂度和空间复杂度
26.Dijkstra(求最短路径)
27.旋转数组找某个数
28.哲学家问题
29.最大连续子序列和
30.最左前缀匹配
31.单链表反转并输出
32.找到非排序数组中未出现的第一个正整数
33.在 0 到 n 这 n+1 个数中取 n 个数,如何找到缺少的那个。
34.链表中如何判断有环路
35.一个二维矩阵 n*n中,n 对应表示各个节点,每个节点之间有连线就在相应位
置上标识1,如何在其中判断出是不是一个图 (任一节点开始遍历,深度遍历,每遍历一个点进行一个标记,当深度遍历到自己访问过的点时,代表存在环,即是个图)
36.二叉树中找出从根到叶子节点中和最大的那条路径
37.实现二叉树的广度优先遍历
38.手写直接插入排序
39.在一个字符串中找出第一个字符出现的位置,保证高效
40.N 级楼梯,一次一步或两步
41.深度优先遍历,广度优先遍历算法 在什么地方可以应用
42.杨辉三角形的算法,第 N 行的数的计算
43.给定两个全都是大写的字符串 a,b a 的长度大于 b 的长度,问如何判断 b 中的所有字符都 在 a 中 ( 首 先 a,b 排 序 , 然 后 再 两 列 比 较 ) 44.一致性哈希算法
45.手写双向链表删除倒数第二个结点并分析
46.找到数组第三大数,没有则返回最大数
47.如何找到一条单链表的中间结点
48.从 10 亿个数中找不重复的数
将 10 亿个数排序后存在不同子文件中,每个子文件在内存中用 HashMap 来进行判断,比如放入 map 中是(int 和boolean 它们封装类的键值对),第一次放进去时候 boolean 为false,当 map 中有这个数之后再放进去时,将 false 改为 true。最后遍历 map 找出为 false 的数就是不重复的。
49.判断二叉树是否为平衡二叉树。
50.0G 文件的淘宝商品编号,只有 512M 内存,怎么判断究竟是不是合法编号(即编号是否存在)
51.假如淘宝存着一个包含 10w 个敏感词的词库,紧接着需要从多个商品标题中随机抽查 3个有没有包含敏感词的商品
52. 查找中间链表元素
53. 图算法
54 平衡树的旋转·
55.一道算法题,在一个整形数组中,有正数有负数,找出和最大的子串
54. 动态规划的思想
55. 给出一个字符数组,找出第一个出现次数最多的字符,注意是第一个
58.一个无序数组找第 K 大的元素
59.找出数组两个数的和等于给定的数
56. 无序数组找中位数(时间复杂度为 logN),
61.两个有序数组找中位数(时间复杂度为 logN)
62.写大数加法代码
63.输出二叉树从左边看过去能看到的所有节点
64.算法题:给定一个翻转过的有序数组,找出翻转点的下标,如:原数组 1,2,3,5,6, 7,8,翻转后的数组 5,6,7,8,1,2,3,翻转点下标是 5
57. 字符串反转
58. 拓扑排序
59. .树的中序遍历,除了递归和栈还有什么实现方式 中序遍历的非递归做法?引出 BFS和 DFS 的区别
60. 拓扑排序思想
61. 给定n 个数,寻找第 k 小的数
62. 写了一个小程序,给定一段字符串,主要为赋值型的字符串,让把它们对应到 map 里 面
63. 1000 以内的素数
64. 手写希尔排序
65. 利用数组,实现一个循环队列类
66. 写一个汉诺塔问题,打印出转移路径,接着写一个二叉树前序遍历的代码,最后让写一 个多叉树实现,并层次遍历的代码,连写四个代码
94.第一道题是一个字母组成的字符串,对该字符串字母序进行排序,大写在小写前面,时间 复杂 度 O(n),如 AaB 是有序的,ABa 是无序的。第二道题计算 f(x,n)=x+x2+…+xn,要求乘法次数最少。
67. 拓扑排序思想
96.一个字符串数组,现给定一个 string 去进行找出对应的数组中字符串的下标 (可以有容错,但两字符串长度必须一致,容错为 2)
例如: [“hello”,“hj”,“abc”] key=“hellg" 返回下角标 0
68. 图的 prime 算法 kruskal 算法 dijkstra 算法 解决什么问题? 分别写一下 伪代码
69. 从一堆字符串中,去除重复的字符,并输出
70. 手写 Kmp 算法
71. 对一个基本有序的数组应该采用什么方式进行排序,对一个乱序的数组应该采用什么方式排序能快速找到前 n 个数?为什么?
72. 给定一个数组, 里面放置任意数量的随机数, 如何快速统计出数组中重复的数字以及出现次数
73. 给定字母集合(a-z), 求出由集合中这些字母组成的所有非空子集
74. 第一道题是用 5 行代码实现字符个数统计;第二题是反转单链表;第三题快速排序
75. 接着推导快速排序的时间复杂度为什么是 O(nlogn)?
76. 并发场景下的多线程代码水题
77. 算法题 一个数组里的数据只有一个是 3 个相同的,其他都是两个相同 怎么找出这个 数 围绕上一题优化
78. 字符转 int 型,考虑负数,异常等问题
79. 跳表
80. 给定 n 个左括号以及 n 个右括号,打印出所有合法的括号组合
81. 给定四个点如何判断是否为矩形

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构与算法知识点包括以下内容: 1. 数据结构:数据结构是指数据元素之间的关系和组织方式。常见的数据结构包括线性结构(如数组、链表、栈、队列)、树形结构(如二叉树、堆、哈夫曼树)和图形结构(如邻接矩阵、邻接表)\[1\]。 2. 算法算法是解决问题的一系列步骤或规则。常见的算法包括排序算法(如冒泡排序、快速排序、归并排序)、搜索算法(如线性搜索、二分搜索)、图算法(如深度优先搜索、广度优先搜索)和动态规划算法\[2\]。 3. 动态规划:动态规划是一种通过将问题拆分成一系列重复的子问题来求解问题的方法。它通常以自底向上的方式解决子问题,并将子问题的结果存储起来以避免重复计算\[2\]。 4. 贪心算法:贪心算法是一种通过每次选择局部最优解来得到整体最优解的方法。它通常以自顶向下的方式进行,每次作出贪心选择后将问题简化为规模更小的子问题\[3\]。 5. 位操作:位操作是在二进制数字符号的层面上进行的操作。它可以用来进行快速的比较和计算,比如按位与、按位或、按位异或等操作\[3\]。 这些知识点是数据结构与算法中的基础,掌握它们可以帮助我们更好地理解和解决各种问题。 #### 引用[.reference_title] - *1* [数据结构与算法——知识点总结](https://blog.csdn.net/qq_41750911/article/details/125041841)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [数据结构与算法知识点总结](https://blog.csdn.net/weixin_40922285/article/details/103183295)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值