LeetCode面试题:100道(上)

目录
面试题 01.01. 判定字符是否唯一
面试题 01.02. 判定是否互为字符重排
面试题 01.03. URL 化
面试题 01.04. 回文排列
面试题 01.05. 一次编辑
面试题 01.06. 字符串压缩
面试题 01.07. 旋转矩阵
面试题 01.08. 零矩阵
面试题 01.09. 字符串轮转
面试题 02.01. 移除重复节点
面试题 02.02. 返回倒数第 k 个节点
面试题 02.03. 删除中间节点
面试题 02.04. 分割链表
面试题 02.05. 链表求和
面试题 02.06. 回文链表
面试题 02.08. 环路检测
面试题 03.01. 三合一
面试题 03.02. 栈的最小值
面试题 03.04. 化栈为队
面试题 03.05. 栈排序
面试题 03.06. 动物收容所
面试题 04.04. 检查平衡性
面试题 04.05. 合法二叉搜索树
面试题 04.08. 首个共同祖先
面试题 04.10. 检查子树
面试题 04.12. 求和路径
面试题 05.01. 插入
面试题 05.06. 整数转换
面试题 05.07. 配对交换
面试题 08.01. 三步问题
面试题 08.09. 括号
面试题 08.10. 颜色填充
面试题 10.09. 排序矩阵查找
面试题 16.01. 交换数字
面试题 16.06. 最小差
面试题 16.10. 生存人数
面试题 16.11. 跳水板
面试题 16.21. 交换和
面试题 17.01. 不用加号的加法
面试题 17.04. 消失的数字
面试题 17.12. BiNode
面试题 17.13. 恢复空格
面试题 17.19. 消失的两个数字
面试题 17.20. 连续中值

Stack方法摘要

boolean empty() 测试堆栈是否为空。
E peek() 查看堆栈顶部的对象,但不从堆栈中移除它。
E pop() 移除堆栈顶部的对象,并作为此函数的值返回该对象。
E push(E item) 把项压入堆栈顶部。
int search(Object o) 返回对象在堆栈中的位置,以 1 为基数。

Queue队列方法摘要

boolean add(E e) 将指定的元素插入此队列(如果立即可行且不会违反容量限制),在成功时返回 true,如果当前没有可用的空间,则抛出 IllegalStateException。
E element() 获取,但是不移除此队列的头。
boolean offer(E e) 将指定的元素插入此队列(如果立即可行且不会违反容量限制),当使用有容量限制的队列时,此方法通常要优于 add(E),后者可能无法插入元素,而只是抛出一个异常。
E peek() 获取但不移除此队列的头;如果此队列为空,则返回 null。
E poll() 获取并移除此队列的头,如果此队列为空,则返回 null。
E remove() 获取并移除此队列的头。

面试题 01.01. 判定字符是否唯一

English Version

题目描述

实现一个算法,确定一个字符串 s 的所有字符是否全都不同。

示例 1:

输入: s = "leetcode"
输出: false 

示例 2:

输入: s = "abc"
输出: true

限制:

  • 0 <= len(s) <= 100
  • 如果你不使用额外的数据结构,会很加分。

解法

Python3

class Solution:
    def isUnique(self, astr: str) -> bool:
        sets = set(astr)
        return len(sets) == len(astr)

Java

class Solution {
    public boolean isUnique(String astr) {
        char[] chars = astr.toCharArray();
        int len = chars.length;
        for (int i = 0; i < len - 1; ++i) {
            for (int j = i + 1; j < len; ++j) {
                if (chars[i] == chars[j]) {
                    return false;
                }
            }
        }
        return true;
    }
}


面试题 01.02. 判定是否互为字符重排

English Version

题目描述

给定两个字符串 s1s2,请编写一个程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。

示例 1:

输入: s1 = "abc", s2 = "bca"
输出: true 

示例 2:

输入: s1 = "abc", s2 = "bad"
输出: false

说明:

  • 0 <= len(s1) <= 100
  • 0 <= len(s2) <= 100

解法

Python3

class Solution:
    def CheckPermutation(self, s1: str, s2: str) -> bool:
        return sorted(s1) == sorted(s2)

Java

class Solution {
    public boolean checkPermutation(String s1, String s2) {
        if (s1 == null || s2 == null || s1.length() != s2.length()) {
            return false;
        }
        char[] c1 = s1.toCharArray();
        char[] c2 = s2.toCharArray();
        Arrays.sort(c1);
        Arrays.sort(c2);
        return Arrays.equals(c1, c2);
    }
}


面试题 01.03. URL 化

English Version

题目描述

URL化。编写一种方法,将字符串中的空格全部替换为%20。假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的“真实”长度。(注:用Java实现的话,请使用字符数组实现,以便直接在数组上操作。)

示例1:

 输入:"Mr John Smith    ", 13
 输出:"Mr%20John%20Smith"

示例2:

 输入:"               ", 5
 输出:"%20%20%20%20%20"

提示:

  1. 字符串长度在[0, 500000]范围内。

解法

Python3

class Solution:
    def replaceSpaces(self, S: str, length: int) -> str:
        S = S[:length] if length < len(S) else S
        return S.replace(' ', '%20')

Java

class Solution {
    public String replaceSpaces(String S, int length) {
        char[] c = S.toCharArray();
        int j = c.length;
        for (int i = length - 1; i >= 0; i--) {
            if (c[i] == ' ') {
                c[--j] = '0';
                c[--j] = '2';
                c[--j] = '%';
            } else {
                c[--j] = c[i];
            }
        }
        return new String(c, j, c.length - j);
    }
}
//拓展: 方法说明
//从数组下标为offset开始顺序取出数组codePoints[]中count个整数,并根据此uncode代码点所对应的字符创建一个string对象
public String(int[] codePoints, int offset, int count) {}


面试题 01.04. 回文排列

English Version

题目描述

给定一个字符串,编写一个函数判定其是否为某个回文串的排列之一。

回文串是指正反两个方向都一样的单词或短语。排列是指字母的重新排列。

回文串不一定是字典当中的单词。

 

示例1:

输入:"tactcoa"
输出:true(排列有"tacocat"、"atcocta",等等)

 

解法

用哈希表存储每个字符出现的次数。若次数为奇数的字符超过 1 个,则不是回文排列。

Python3

class Solution:
    def canPermutePalindrome(self, s: str) -> bool:
        if s is None or len(s) < 2:
            return True
        cache = {}
        for ch in s:
            cache[ch] = 1 if cache.get(ch) is None else cache[ch] + 1
        cnt = 0
        for k, v in cache.items():
            if (v & 1) == 1:
                cnt += 1
            if cnt > 1:
                return False
        return cnt <= 1

Java

class Solution {
    public boolean canPermutePalindrome(String s) {
        if (s == null || s.length() < 2) {
            return true;
        }
        char[] chars = s.toCharArray();
        Map<Character, Integer> counter = new HashMap<>();
        for (char ch : chars) {
            counter.put(ch, counter.get(ch) == null ? 1 : counter.get(ch) + 1);
        }
        int cnt = 0;
        for (Map.Entry<Character, Integer> entry : counter.entrySet()) {
            if ((entry.getValue() & 1) == 1) {
                ++cnt;
            }
            if (cnt > 1) {
                return false;
            }
        }
        return cnt <= 1;
    }
}


面试题 01.05. 一次编辑

English Version

题目描述

字符串有三种编辑操作:插入一个字符、删除一个字符或者替换一个字符。 给定两个字符串,编写一个函数判定它们是否只需要一次(或者零次)编辑。

 

示例 1:

输入: 
first = "pale"
second = "ple"
输出: True

 

示例 2:

输入: 
first = "pales"
second = "pal"
输出: False

解法

遍历两个字符串,逐个字符比较判断。

Python3

class Solution:
    def oneEditAway(self, first: str, second: str) -> bool:
        n1, n2 = len(first), len(second)
        if abs(n1 - n2) > 1:
            return False
        if n1 + n2 <= 2:
            return True
        if first[0] != second[0]:
            if n1 == n2:
                return first[1:] == second[1:]
            else:
                return first[1:] == second or second[1:] == first
        else:
            return self.oneEditAway(first[1:], second[1:])

Java

class Solution {
    public boolean oneEditAway(String first, String second) {
        int n1 = first.length(), n2 = second.length();
        int differ = Math.abs(n1 - n2);
        if (differ > 1) {
            return false;
        }
        if (n1 + n2 <= 2) {
            return true;
        }
        if (first.charAt(0) != second.charAt(0)) {
            if (n1 == n2) {
                return first.substring(1).equals(second.substring(1));
            } else {
                return first.substring(1).equals(second) || second.substring(1).equals(first);
            }
        } else {
            return oneEditAway(first.substring(1), second.substring(1));
        }
    }
}


面试题 01.06. 字符串压缩

English Version

题目描述

字符串压缩。利用字符重复出现的次数,编写一种方法,实现基本的字符串压缩功能。比如,字符串aabcccccaaa会变为a2b1c5a3。若“压缩”后的字符串没有变短,则返回原先的字符串。你可以假设字符串中只包含大小写英文字母(a至z)。

示例1:

 输入:"aabcccccaaa"
 输出:"a2b1c5a3"

示例2:

 输入:"abbccd"
 输出:"abbccd"
 解释:"abbccd"压缩后为"a1b2c2d1",比原字符串长度更长。

提示:

  1. 字符串长度在[0, 50000]范围内。

解法

双指针遍历字符串求解。

Python3

class Solution:
    def compressString(self, S: str) -> str:
        if len(S) < 2:
            return S
        p, q = 0, 1
        res = ''
        while q < len(S):
            if S[p] != S[q]:
                res += (S[p] + str(q - p))
                p = q
            q += 1
        res += (S[p] + str(q - p))
        return res if len(res) < len(S) else S

Java

class Solution {
    public String compressString(String S) {
        if (S == null || S.length() < 2) {
            return S;
        }
        char[] chars = S.toCharArray();
        int p = 0, q = 1, n = chars.length;
        StringBuilder sb = new StringBuilder();
        while (q < n) {
            if (chars[p] != chars[q]) {
                sb.append(chars[p]).append(q - p);
                p = q;
            }
            q += 1;
        }
        sb.append(chars[p]).append(q - p);
        String res = sb.toString();
        return res.length() < n ? res : S;
    }
}


面试题 01.07. 旋转矩阵

English Version

题目描述

给定一幅由N × N矩阵表示的图像,其中每个像素的大小为4字节,编写一种方法,将图像旋转90度。

不占用额外内存空间能否做到?

 

示例 1:

给定 matrix = 
[
  [1,2,3],
  [4,5,6],
  [7,8,9]
],

原地旋转输入矩阵,使其变为:
[
  [7,4,1],
  [8,5,2],
  [9,6,3]
]

示例 2:

给定 matrix =
[
  [ 5, 1, 9,11],
  [ 2, 4, 8,10],
  [13, 3, 6, 7],
  [15,14,12,16]
], 

原地旋转输入矩阵,使其变为:
[
  [15,13, 2, 5],
  [14, 3, 4, 1],
  [12, 6, 8, 9],
  [16, 7,10,11]
]

解法

原地旋转,i 的范围是 [0, n/2),j 的范围是 [i, n-1-i)

Python3

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        n = len(matrix)
        for i in range(n // 2):
            for j in range(i, n - 1 - i):
                t = matrix[i][j]
                matrix[i][j] = matrix[n - j - 1][i]
                matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1]
                matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1]
                matrix[j][n - i - 1] = t

Java

class Solution {
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        for (int i = 0; i < n / 2; ++i) {
            for (int j = i; j < n - 1 - i; ++j) {
                int t = matrix[i][j];
                matrix[i][j] = matrix[n - j - 1][i];
                matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
                matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
                matrix[j][n - i - 1] = t;
            }
        }
    }
}


面试题 01.08. 零矩阵

English Version

题目描述

编写一种算法,若M × N矩阵中某个元素为0,则将其所在的行与列清零。

 

示例 1:

输入:
[
  [1,1,1],
  [1,0,1],
  [1,1,1]
]
输出:
[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]

示例 2:

输入:
[
  [0,1,2,0],
  [3,4,5,2],
  [1,3,1,5]
]
输出:
[
  [0,0,0,0],
  [0,4,5,0],
  [0,3,1,0]
]

解法

用 set 记录需要清零的行 zero_rows 跟列 zero_cols,之后分别将需要清零的行、列上的所有元素清零。

Python3

class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        rows, cols = len(matrix), len(matrix[0])
        zero_rows, zero_cols = set(), set()
        for i in range(rows):
            for j in range(cols):
                if matrix[i][j] == 0:
                    zero_rows.add(i)
                    zero_cols.add(j)

        # 行清零
        for i in zero_rows:
            for j in range(cols):
                matrix[i][j] = 0

        # 列清零
        for j in zero_cols:
            for i in range(rows):
                matrix[i][j] = 0

        return matrix

Java

class Solution {
    public void setZeroes(int[][] matrix) {
        int rows = matrix.length, cols = matrix[0].length;
        Set<Integer> zeroRows = new HashSet<>();
        Set<Integer> zeroCols = new HashSet<>();
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                if (matrix[i][j] == 0) {
                    zeroRows.add(i);
                    zeroCols.add(j);
                }
            }
        }

        // 行清零
        for (int row : zeroRows) {
            for (int j = 0; j < cols; ++j) {
                matrix[row][j] = 0;
            }
        }

        // 列清零
        for (int col : zeroCols) {
            for (int i = 0; i < rows; ++i) {
                matrix[i][col] = 0;
            }
        }
    }
}


面试题 01.09. 字符串轮转

English Version

题目描述

字符串轮转。给定两个字符串s1s2,请编写代码检查s2是否为s1旋转而成(比如,waterbottleerbottlewat旋转后的字符串)。

示例1:

 输入:s1 = "waterbottle", s2 = "erbottlewat"
 输出:True

示例2:

 输入:s1 = "aa", "aba"
 输出:False

    提示:

    1. 字符串长度在[0, 100000]范围内。

    说明:

    1. 你能只调用一次检查子串的方法吗?

    解法

    Python3

    class Solution:
        def isFlipedString(self, s1: str, s2: str) -> bool:
            return len(s1) == len(s2) and s1 in (s2 * 2)
    

    Java

    class Solution {
        public boolean isFlipedString(String s1, String s2) {
            return s1.length() == s2.length() && (s2 + s2).indexOf(s1) != -1;
            //等价于 return s1.length() == s2.length() && (s2 + s2).contains(s1);        
        }
    }
    

    
    

    面试题 02.01. 移除重复节点

    English Version

    题目描述

    编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。

    示例1:

     输入:[1, 2, 3, 3, 2, 1]
     输出:[1, 2, 3]
    

    示例2:

     输入:[1, 1, 1, 1, 2]
     输出:[1, 2]
    

    提示:

    1. 链表长度在[0, 20000]范围内。
    2. 链表元素在[0, 20000]范围内。

    进阶:

    如果不得使用临时缓冲区,该怎么解决?

    解法

    Python3

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        def removeDuplicateNodes(self, head: ListNode) -> ListNode:
            if head is None or head.next is None:
                return head
            cache = set()
            cache.add(head.val)
            cur, p = head, head.next
            while p:
                if p.val not in cache:
                    cur.next = p
                    cur = cur.next
                    cache.add(p.val)
                p = p.next
            cur.next = None
            return head
    

    Java

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public ListNode removeDuplicateNodes(ListNode head) {
            if (head == null || head.next == null) {
                return head;
            }
            Set<Integer> s = new HashSet<>();
            s.add(head.val);
            ListNode p = head.next, cur = head;
            while (p != null) {
                if (!s.contains(p.val)) {
                    cur.next = p;
                    cur = cur.next;
                    s.add(p.val);
                }
                p = p.next;
            }
            cur.next = null;
            return head;
    
        }
    }
    

    
    

    面试题 02.02. 返回倒数第 k 个节点

    English Version

    题目描述

    实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。

    注意:本题相对原题稍作改动

    示例:

    输入: 1->2->3->4->5 和 k = 2
    输出: 4

    说明:

    给定的 k 保证是有效的。

    解法

    定义 pq 指针指向 head

    p 先向前走 k 步,接着 pq 同时向前走,当 p 指向 null 时,q 指向的节点即为链表的倒数第 k 个节点。

    Python3

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        def kthToLast(self, head: ListNode, k: int) -> int:
            p = q = head
            for _ in range(k):
                q = q.next
            while q:
                p, q = p.next, q.next
            return p.val
    

    Java

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public int kthToLast(ListNode head, int k) {
            ListNode p = head, q = head;
            while (k-- > 0) {
                q = q.next;
            }
            while (q != null) {
                q = q.next;
                p = p.next;
            }
            return p.val;
        }
    }
    

    
    

    面试题 02.03. 删除中间节点

    English Version

    题目描述

    实现一种算法,删除单向链表中间的某个节点(除了第一个和最后一个节点,不一定是中间节点),假定你只能访问该节点。

     

    示例:

    输入:单向链表a->b->c->d->e->f中的节点c
    结果:不返回任何数据,但该链表变为a->b->d->e->f
    

    解法

    把 node 的下一个节点的值赋给 node,然后改变 node 的 next 指向。

    Python3

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        def deleteNode(self, node):
            """
            :type node: ListNode
            :rtype: void Do not return anything, modify node in-place instead.
            """
            node.val = node.next.val
            node.next = node.next.next
    

    Java

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public void deleteNode(ListNode node) {
            node.val = node.next.val;
            node.next = node.next.next;
        }
    }
    

    
    

    面试题 02.04. 分割链表

    English Version

    题目描述

    编写程序以 x 为基准分割链表,使得所有小于 x 的节点排在大于或等于 x 的节点之前。如果链表中包含 x,x 只需出现在小于 x 的元素之后(如下所示)。分割元素 x 只需处于“右半部分”即可,其不需要被置于左右两部分之间。

    示例:

    输入: head = 3->5->8->5->10->2->1, x = 5
    输出: 3->1->2->10->5->5->8
    

    解法

    创建两个链表,一个存放小于 x 的节点,另一个存放大于等于 x 的节点,之后进行拼接即可。

    Python3

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        def partition(self, head: ListNode, x: int) -> ListNode:
            if head is None or head.next is None:
                return head
            left, right = ListNode(-1), ListNode(-1)
            p, q = left, right
            while head:
                t = head.next
                head.next = None
                if head.val < x:
                    p.next = head
                    p = p.next
                else:
                    q.next = head
                    q = q.next
                head = t
            p.next = right.next
            return left.next
    

    Java

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public ListNode partition(ListNode head, int x) {
            if (head == null || head.next == null) {
                return head;
            }
            ListNode left = new ListNode(-1);
            ListNode right = new ListNode(-1);
            ListNode p = left, q = right;
            while (head != null) {
                ListNode t = head.next;
                head.next = null;
                if (head.val < x) {
                    p.next = head;
                    p = p.next;
                } else {
                    q.next = head;
                    q = q.next;
                }
                head = t;
            }
            p.next = right.next;
            return left.next;
        }
    }
    

    
    

    面试题 02.05. 链表求和

    English Version

    题目描述

    给定两个用链表表示的整数,每个节点包含一个数位。

    这些数位是反向存放的,也就是个位排在链表首部。

    编写函数对这两个整数求和,并用链表形式返回结果。

     

    示例:

    输入:(7 -> 1 -> 6) + (5 -> 9 -> 2),即617 + 295
    输出:2 -> 1 -> 9,即912
    

    进阶:假设这些数位是正向存放的,请再做一遍。

    示例:

    输入:(6 -> 1 -> 7) + (2 -> 9 -> 5),即617 + 295
    输出:9 -> 1 -> 2,即912
    

    解法

    同时遍历两链表,求节点的和与进位。

    Python3

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
            p = ListNode(-1)
            carry, t = 0, p
            while l1 or l2:
                s = (0 if l1 is None else l1.val) + (0 if l2 is None else l2.val) + carry
                carry = 1 if s > 9 else 0
                t.next = ListNode(s % 10)
                t = t.next
                l1 = l1.next if l1 else l1
                l2 = l2.next if l2 else l2
            t.next = None if carry == 0 else ListNode(carry)
            return p.next
    
    
    

    Java

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
            ListNode p = new ListNode(-1);
            int carry = 0;
            ListNode t = p;
            while (l1 != null || l2 != null) {
                int s = (l1 == null ? 0 : l1.val) + (l2 == null ? 0 : l2.val) + carry;
                t.next = new ListNode(s % 10);
                carry = s > 9 ? 1 : 0;
                t = t.next;
                l1 = l1 == null ? l1 : l1.next;
                l2 = l2 == null ? l2 : l2.next;
            }
            t.next = carry == 0 ? null : new ListNode(carry);
            return p.next;
        }
    }
    

    
    

    面试题 02.06. 回文链表

    English Version

    题目描述

    编写一个函数,检查输入的链表是否是回文的。

     

    示例 1:

    输入: 1->2
    输出: false 
    

    示例 2:

    输入: 1->2->2->1
    输出: true 
    

     

    进阶:
    你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

    解法

    先用快慢指针找到链表的中点,接着反转右半部分的链表。然后同时遍历前后两段链表,若前后两段链表节点对应的值不等,说明不是回文链表,否则说明是回文链表。

    Python3

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    class Solution:
        def isPalindrome(self, head: ListNode) -> bool:
            if head is None or head.next is None:
                return True
            slow, fast = head, head.next
            while fast and fast.next:
                slow, fast = slow.next, fast.next.next
            pre, cur = None, slow.next
            while cur:
                t = cur.next
                cur.next = pre
                pre, cur = cur, t
            while pre:
                if pre.val != head.val:
                    return False
                pre, head = pre.next, head.next
            return True
    

    Java

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public boolean isPalindrome(ListNode head) {
            if (head == null || head.next == null) {
                return true;
            }
            ListNode slow = head;
            ListNode fast = head.next;
            while (fast != null && fast.next != null) {
                slow = slow.next;
                fast = fast.next.next;
            }
            ListNode cur = slow.next;
            slow.next = null;
            ListNode pre = null;
            while (cur != null) {
                ListNode t = cur.next;
                cur.next = pre;
                pre = cur;
                cur = t;
            }
            while (pre != null) {
                if (pre.val != head.val) {
                    return false;
                }
                pre = pre.next;
                head = head.next;
            }
            return true;
        }
    }
    

    
    

    面试题 02.08. 环路检测

    English Version

    题目描述

    给定一个有环链表,实现一个算法返回环路的开头节点。
    有环链表的定义:在链表中某个节点的next元素指向在它前面出现过的节点,则表明该链表存在环路。


    示例 1:

    输入:head = [3,2,0,-4], pos = 1
    输出:tail connects to node index 1
    解释:链表中有一个环,其尾部连接到第二个节点。


    示例 2:

    输入:head = [1,2], pos = 0
    输出:tail connects to node index 0
    解释:链表中有一个环,其尾部连接到第一个节点。


    示例 3:

    输入:head = [1], pos = -1
    输出:no cycle
    解释:链表中没有环。


    进阶:
    你是否可以不用额外空间解决此题?

    解法

    Python3

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        def detectCycle(self, head: ListNode) -> ListNode:
            fast = slow = p = head
            while fast and fast.next:
                fast = fast.next.next
                slow = slow.next
                if fast == slow:
                    break
            if fast is None or fast.next is None:
                return None
            while slow != p:
                p = p.next
                slow = slow.next
            return p
    

    Java

    /**
     * Definition for singly-linked list.
     * class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) {
     *         val = x;
     *         next = null;
     *     }
     * }
     */
    public class Solution {
        public ListNode detectCycle(ListNode head) {
             ListNode fast = head, slow = head;
             while (fast != null && fast.next != null) {
                 fast = fast.next.next;
                 slow = slow.next;
                 if (fast == slow) break;
             }
             if (fast == null || fast.next == null) return null;
             ListNode p = head;
             while (p != slow) {
                 p = p.next;
                 slow = slow.next;
             }
             return p;
        }
    }
    

    
    

    面试题 03.01. 三合一

    English Version

    题目描述

    三合一。描述如何只用一个数组来实现三个栈。

    你应该实现push(stackNum, value)pop(stackNum)isEmpty(stackNum)peek(stackNum)方法。stackNum表示栈下标,value表示压入的值。

    构造函数会传入一个stackSize参数,代表每个栈的大小。

    示例1:

     输入:
    ["TripleInOne", "push", "push", "pop", "pop", "pop", "isEmpty"]
    [[1], [0, 1], [0, 2], [0], [0], [0], [0]]
     输出:
    [null, null, null, 1, -1, -1, true]
    说明:当栈为空时`pop, peek`返回-1,当栈满时`push`不压入元素。
    

    示例2:

     输入:
    ["TripleInOne", "push", "push", "push", "pop", "pop", "pop", "peek"]
    [[2], [0, 1], [0, 2], [0, 3], [0], [0], [0], [0]]
     输出:
    [null, null, null, null, 2, 1, -1, -1]
    

    解法

    二维数组解决;也可以使用一维数组,以下标 0,3,6,..1,4,7,..2,5,8,.. 区分,一维数组最后三个元素记录每个栈的元素个数。

    Python3

    class TripleInOne:
    
        def __init__(self, stackSize: int):
            self._capacity = stackSize
            self._s = [[], [], []]
    
        def push(self, stackNum: int, value: int) -> None:
            if len(self._s[stackNum]) < self._capacity:
                self._s[stackNum].append(value)
    
        def pop(self, stackNum: int) -> int:
            return -1 if self.isEmpty(stackNum) else self._s[stackNum].pop()
    
        def peek(self, stackNum: int) -> int:
            return -1 if self.isEmpty(stackNum) else self._s[stackNum][-1]
    
        def isEmpty(self, stackNum: int) -> bool:
            return len(self._s[stackNum]) == 0
    
    
    # Your TripleInOne object will be instantiated and called as such:
    # obj = TripleInOne(stackSize)
    # obj.push(stackNum,value)
    # param_2 = obj.pop(stackNum)
    # param_3 = obj.peek(stackNum)
    # param_4 = obj.isEmpty(stackNum)
    

    Java

    class TripleInOne {
        private int[] s;
        private int capacity;
    
        public TripleInOne(int stackSize) {
            s = new int[stackSize * 3 + 3];
            capacity = stackSize;
        }
    
        public void push(int stackNum, int value) {
            if (s[stackNum + 3 * capacity] < capacity) {
                s[s[stackNum + 3 * capacity] * 3 + stackNum] = value;
                ++s[stackNum + 3 * capacity];
            }
        }
    
        public int pop(int stackNum) {
            if (isEmpty(stackNum)) {
                return -1;
            }
            --s[stackNum + 3 * capacity];
            return s[s[stackNum + 3 * capacity] * 3 + stackNum];
        }
    
        public int peek(int stackNum) {
            return isEmpty(stackNum) ? -1 : s[(s[stackNum + 3 * capacity] - 1) * 3 + stackNum];
        }
    
        public boolean isEmpty(int stackNum) {
            return s[stackNum + 3 * capacity] == 0;
        }
    }
    
    /**
     * Your TripleInOne object will be instantiated and called as such:
     * TripleInOne obj = new TripleInOne(stackSize);
     * obj.push(stackNum,value);
     * int param_2 = obj.pop(stackNum);
     * int param_3 = obj.peek(stackNum);
     * boolean param_4 = obj.isEmpty(stackNum);
     */
    

    
    

    面试题 03.02. 栈的最小值

    English Version

    题目描述

    请设计一个栈,除了常规栈支持的pop与push函数以外,还支持min函数,该函数返回栈元素中的最小值。执行push、pop和min操作的时间复杂度必须为O(1)。


    示例:

    MinStack minStack = new MinStack();
    minStack.push(-2);
    minStack.push(0);
    minStack.push(-3);
    minStack.getMin(); --> 返回 -3.
    minStack.pop();
    minStack.top(); --> 返回 0.
    minStack.getMin(); --> 返回 -2.

    解法

    利用辅助栈存放栈的最小元素。

    Python3

    class MinStack:
    
        def __init__(self):
            """
            initialize your data structure here.
            """
            self._s1 = []
            self._s2 = []
    
    
        def push(self, x: int) -> None:
            self._s1.append(x)
            self._s2.append(x if len(self._s2) == 0 or self._s2[-1] >= x else self._s2[-1])
    
        def pop(self) -> None:
            self._s1.pop()
            self._s2.pop()
    
        def top(self) -> int:
            return self._s1[-1]
    
        def getMin(self) -> int:
            return self._s2[-1]
    
    
    # Your MinStack object will be instantiated and called as such:
    # obj = MinStack()
    # obj.push(x)
    # obj.pop()
    # param_3 = obj.top()
    # param_4 = obj.getMin()
    

    Java

    class MinStack {
        private Stack<Integer> s1;
        private Stack<Integer> s2;
    
        /** initialize your data structure here. */
        public MinStack() {
            s1 = new Stack<>();
            s2 = new Stack<>();
        }
    
        public void push(int x) {
            s1.push(x);
            s2.push(s2.empty() || s2.peek() >= x ? x : s2.peek());
        }
    
        public void pop() {
            s1.pop();
            s2.pop();
        }
    
        public int top() {
            return s1.peek();
        }
    
        public int getMin() {
            return s2.empty() ? -1 : s2.peek();
        }
    }
    
    /**
     * Your MinStack object will be instantiated and called as such:
     * MinStack obj = new MinStack();
     * obj.push(x);
     * obj.pop();
     * int param_3 = obj.top();
     * int param_4 = obj.getMin();
     */
    

    
    

    面试题 03.04. 化栈为队

    English Version

    题目描述

    实现一个MyQueue类,该类用两个栈来实现一个队列。


    示例:

    MyQueue queue = new MyQueue();

    queue.push(1);
    queue.push(2);
    queue.peek(); // 返回 1
    queue.pop(); // 返回 1
    queue.empty(); // 返回 false


    说明:

    • 你只能使用标准的栈操作 -- 也就是只有 push to top, peek/pop from top, sizeis empty 操作是合法的。
    • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
    • 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。

    解法

    • 每次压入元素时,放入第 1 个栈中;
    • 第 2 个栈不为空时,不能倒入元素;
    • 第 2 个栈为空时,必须将第 1 个栈的所有元素按顺序倒入第 2 个栈中。

    Python3

    class MyQueue:
    
        def __init__(self):
            """
            Initialize your data structure here.
            """
            self._s1, self._s2 = [], []
    
    
        def push(self, x: int) -> None:
            """
            Push element x to the back of queue.
            """
            self._s1.append(x)
    
    
        def pop(self) -> int:
            """
            Removes the element from in front of queue and returns that element.
            """
            if len(self._s2) == 0:
                while self._s1:
                    self._s2.append(self._s1.pop())
            return self._s2.pop()
    
    
        def peek(self) -> int:
            """
            Get the front element.
            """
            if len(self._s2) == 0:
                while self._s1:
                    self._s2.append(self._s1.pop())
            return self._s2[-1]
    
    
        def empty(self) -> bool:
            """
            Returns whether the queue is empty.
            """
            return len(self._s1) + len(self._s2) == 0
    
    
    
    # Your MyQueue object will be instantiated and called as such:
    # obj = MyQueue()
    # obj.push(x)
    # param_2 = obj.pop()
    # param_3 = obj.peek()
    # param_4 = obj.empty()
    

    Java

    class MyQueue {
        private Stack<Integer> s1;
        private Stack<Integer> s2;
    
        /** Initialize your data structure here. */
        public MyQueue() {
            s1 = new Stack<>();
            s2 = new Stack<>();
        }
    
        /** Push element x to the back of queue. */
        public void push(int x) {
            s1.push(x);
        }
    
        /** Removes the element from in front of queue and returns that element. */
        public int pop() {
            if (s2.empty()) {
                while (!s1.empty()) {
                    s2.push(s1.pop());
                }
            }
            return s2.pop();
        }
    
        /** Get the front element. */
        public int peek() {
            if (s2.empty()) {
                while (!s1.empty()) {
                    s2.push(s1.pop());
                }
            }
            return s2.peek();
        }
    
        /** Returns whether the queue is empty. */
        public boolean empty() {
            return s1.empty() && s2.empty();
        }
    }
    
    /**
     * Your MyQueue object will be instantiated and called as such:
     * MyQueue obj = new MyQueue();
     * obj.push(x);
     * int param_2 = obj.pop();
     * int param_3 = obj.peek();
     * boolean param_4 = obj.empty();
     */
    

    
    

    面试题 03.05. 栈排序

    English Version

    题目描述

    栈排序。 编写程序,对栈进行排序使最小元素位于栈顶。最多只能使用一个其他的临时栈存放数据,但不得将元素复制到别的数据结构(如数组)中。该栈支持如下操作:pushpoppeekisEmpty。当栈为空时,peek 返回 -1。

    示例1:

     输入:
    ["SortedStack", "push", "push", "peek", "pop", "peek"]
    [[], [1], [2], [], [], []]
     输出:
    [null,null,null,1,null,2]
    

    示例2:

     输入: 
    ["SortedStack", "pop", "pop", "push", "pop", "isEmpty"]
    [[], [], [], [1], [], []]
     输出:
    [null,null,null,null,null,true]
    

    说明:

    1. 栈中的元素数目在[0, 5000]范围内。

    解法

    利用辅助栈实现 push 操作,其余操作不变。

    Python3

    class SortedStack:
    
        def __init__(self):
            self.s = []
    
        def push(self, val: int) -> None:
            t = []
            while not self.isEmpty() and self.s[-1] < val:
                t.append(self.s.pop())
            self.s.append(val)
            while len(t) > 0:
                self.s.append(t.pop())
    
        def pop(self) -> None:
            if not self.isEmpty():
                self.s.pop()
    
        def peek(self) -> int:
            return -1 if self.isEmpty() else self.s[-1]
    
        def isEmpty(self) -> bool:
            return len(self.s) == 0
    

    Java

    class SortedStack {
        private Stack<Integer> s;
        public SortedStack() {
            s = new Stack<>();
        }
    
        public void push(int val) {
            Stack<Integer> t = new Stack<>();
            while (!isEmpty() && s.peek() < val) {
                t.push(s.pop());
            }
            s.push(val);
            while (!t.isEmpty()) {
                s.push(t.pop());
            }
        }
    
        public void pop() {
            if (!isEmpty()) {
                s.pop();
            }
        }
    
        public int peek() {
            return isEmpty() ? -1 : s.peek();
        }
    
        public boolean isEmpty() {
            return s.isEmpty();
        }
    }
    
    /**
     * Your SortedStack object will be instantiated and called as such:
     * SortedStack obj = new SortedStack();
     * obj.push(val);
     * obj.pop();
     * int param_3 = obj.peek();
     * boolean param_4 = obj.isEmpty();
     */
    

    
    

    面试题 03.06. 动物收容所

    English Version

    题目描述

    动物收容所。有家动物收容所只收容狗与猫,且严格遵守“先进先出”的原则。在收养该收容所的动物时,收养人只能收养所有动物中“最老”(由其进入收容所的时间长短而定)的动物,或者可以挑选猫或狗(同时必须收养此类动物中“最老”的)。换言之,收养人不能自由挑选想收养的对象。请创建适用于这个系统的数据结构,实现各种操作方法,比如enqueuedequeueAnydequeueDogdequeueCat。允许使用Java内置的LinkedList数据结构。

    enqueue方法有一个animal参数,animal[0]代表动物编号,animal[1]代表动物种类,其中 0 代表猫,1 代表狗。

    dequeue*方法返回一个列表[动物编号, 动物种类],若没有可以收养的动物,则返回[-1,-1]

    示例1:

     输入:
    ["AnimalShelf", "enqueue", "enqueue", "dequeueCat", "dequeueDog", "dequeueAny"]
    [[], [[0, 0]], [[1, 0]], [], [], []]
     输出:
    [null,null,null,[0,0],[-1,-1],[1,0]]
    

    示例2:

     输入:
    ["AnimalShelf", "enqueue", "enqueue", "enqueue", "dequeueDog", "dequeueCat", "dequeueAny"]
    [[], [[0, 0]], [[1, 0]], [[2, 1]], [], [], []]
     输出:
    [null,null,null,null,[2,1],[0,0],[1,0]]
    

    说明:

    1. 收纳所的最大容量为20000

    解法

    双队列存储。

    Python3

    class AnimalShelf:
    
        def __init__(self):
            self.cats = []
            self.dogs = []
    
        def enqueue(self, animal: List[int]) -> None:
            if animal[1] == 0:
                self.cats.insert(0, animal[0])
            else:
                self.dogs.insert(0, animal[0])
    
        def dequeueAny(self) -> List[int]:
            if len(self.dogs) == 0: return self.dequeueCat()
            if len(self.cats) == 0: return self.dequeueDog()
            return self.dequeueDog() if self.dogs[-1] < self.cats[-1] else self.dequeueCat()
    
        def dequeueDog(self) -> List[int]:
            return [-1, -1] if len(self.dogs) == 0 else [self.dogs.pop(), 1]
    
        def dequeueCat(self) -> List[int]:
            return [-1, -1] if len(self.cats) == 0 else [self.cats.pop(), 0]
    
    
    # Your AnimalShelf object will be instantiated and called as such:
    # obj = AnimalShelf()
    # obj.enqueue(animal)
    # param_2 = obj.dequeueAny()
    # param_3 = obj.dequeueDog()
    # param_4 = obj.dequeueCat()
    

    Java

    class AnimalShelf {
        Queue<Integer> cats;
        Queue<Integer> dogs;
        public AnimalShelf() {
            cats = new LinkedList<>();
            dogs = new LinkedList<>();
        }
    
        public void enqueue(int[] animal) {
            if (animal[1] == 0) {
                cats.offer(animal[0]);
            } else {
                dogs.offer(animal[0]);
            }
        }
    
        public int[] dequeueAny() {
            return dogs.isEmpty() ? dequeueCat() : (cats.isEmpty() ? dequeueDog() : (dogs.peek() < cats.peek() ? dequeueDog() : dequeueCat()));
        }
    
        public int[] dequeueDog() {
            return dogs.isEmpty() ? new int[]{-1, -1} : new int[]{dogs.poll(), 1};
        }
    
        public int[] dequeueCat() {
            return cats.isEmpty() ? new int[]{-1, -1} : new int[]{cats.poll(), 0};
        }
    }
    
    /**
     * Your AnimalShelf object will be instantiated and called as such:
     * AnimalShelf obj = new AnimalShelf();
     * obj.enqueue(animal);
     * int[] param_2 = obj.dequeueAny();
     * int[] param_3 = obj.dequeueDog();
     * int[] param_4 = obj.dequeueCat();
     */
    

    
    

    面试题 04.04. 检查平衡性

    English Version

    题目描述

    实现一个函数,检查二叉树是否平衡。在这个问题中,平衡树的定义如下:任意一个节点,其两棵子树的高度差不超过 1。


    示例 1:
    给定二叉树 [3,9,20,null,null,15,7]
    3
    / \
    9 20
    / \
    15 7
    返回 true 。
    示例 2:
    给定二叉树 [1,2,2,3,3,null,null,4,4]
    1
    / \
    2 2
    / \
    3 3
    / \
    4 4
    返回 false 。

    解法

    递归法。

    Python3

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def isBalanced(self, root: TreeNode) -> bool:
            if not root:
                return True
            l, r = self._height(root.left), self._height(root.right)
            return abs(l - r) < 2 and self.isBalanced(root.left) and self.isBalanced(root.right)
    
        def _height(self, node):
            if not node:
                return 0
            return 1 + max(self._height(node.left), self._height(node.right))
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public boolean isBalanced(TreeNode root) {
            if (root == null) {
                return true;
            }
            int l = height(root.left), r = height(root.right);
            return Math.abs(l - r) < 2 && isBalanced(root.left) && isBalanced(root.right);
        }
    
        private int height(TreeNode node) {
            if (node == null) {
                return 0;
            }
            return 1 + Math.max(height(node.left), height(node.right));
        }
    }
    

    
    

    面试题 04.05. 合法二叉搜索树

    English Version

    题目描述

    实现一个函数,检查一棵二叉树是否为二叉搜索树。

    示例 1:
    输入:
    2
    / \
    1 3
    输出: true
    示例 2:
    输入:
    5
    / \
    1 4
    / \
    3 6
    输出: false
    解释: 输入为: [5,1,4,null,null,3,6]。
    根节点的值为 5 ,但是其右子节点值为 4 。

    解法

    一棵合法的二叉搜索树,其中序遍历的结果应该升序排列。

    Python3

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        res, t = True, None
        def isValidBST(self, root: TreeNode) -> bool:
            self.isValid(root)
            return self.res
    
        def isValid(self, root):
            if not root:
                return
            self.isValid(root.left)
            if self.t is None or self.t < root.val:
                self.t = root.val
            else:
                self.res = False
                return
            self.isValid(root.right)
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        private boolean res = true;
        private Integer t = null;
        public boolean isValidBST(TreeNode root) {
            isValid(root);
            return res;
        }
    
        private void isValid(TreeNode root) {
            if (root == null) {
                return;
            }
            isValid(root.left);
            if (t == null || t < root.val) {
                t = root.val;
            } else {
                res = false;
                return;
            }
            isValid(root.right);
        }
    }
    

    
    

    面试题 04.08. 首个共同祖先

    English Version

    题目描述

    设计并实现一个算法,找出二叉树中某两个节点的第一个共同祖先。不得将其他的节点存储在另外的数据结构中。注意:这不一定是二叉搜索树。

    例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]

        3
    / \
    5 1
    / \ / \
    6 2 0 8
    / \
    7 4
    示例 1:
    输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
    输入: 3
    解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
    示例 2:
    输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
    输出: 5
    解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。
    说明:
    所有节点的值都是唯一的。
    p、q 为不同节点且均存在于给定的二叉树中。

    解法

    Python3

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
            if root is None or root == p or root == q:
                return root
            left = self.lowestCommonAncestor(root.left, p, q)
            right = self.lowestCommonAncestor(root.right, p, q)
            return right if left is None else (left if right is None else root)
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
            if (root == null || root == p || root == q) {
                return root;
            }
            TreeNode left = lowestCommonAncestor(root.left, p, q);
            TreeNode right = lowestCommonAncestor(root.right, p, q);
            return left == null ? right : (right == null ? left : root);
        }
    }
    

    
    

    面试题 04.10. 检查子树

    English Version

    题目描述

    检查子树。你有两棵非常大的二叉树:T1,有几万个节点;T2,有几万个节点。设计一个算法,判断 T2 是否为 T1 的子树。

    如果 T1 有这么一个节点 n,其子树与 T2 一模一样,则 T2 为 T1 的子树,也就是说,从节点 n 处把树砍断,得到的树与 T2 完全相同。

    示例1:

     输入:t1 = [1, 2, 3], t2 = [2]
     输出:true
    

    示例2:

     输入:t1 = [1, null, 2, 4], t2 = [3, 2]
     输出:false
    

    提示:

    1. 树的节点数目范围为[0, 20000]。

    解法

    先找 t1 中 t2 结点,找到后进行 DFS,确认子树和 t2 的子树完全相同,否则返回 FALSE。

    Python3

    class Solution:
        def checkSubTree(self, t1: TreeNode, t2: TreeNode) -> bool:
            if t1 == None:
                return False
            if t2 == None:
                return True
            return self.dfs(t1,t2) or self.checkSubTree(t1.left,t2) or self.checkSubTree(t1.right,t2)
    
        def dfs(self, t1: TreeNode, t2: TreeNode) -> bool:
            if not t1 and t2 :
                return False
            if not t2 and not t1:
                return True
            if t1.val != t2.val:
                return False
            else:
                return self.dfs(t1.left,t2.left) and self.dfs(t1.right,t2.right)
    

    Java

    class Solution {
        public boolean checkSubTree(TreeNode t1, TreeNode t2) {
            if (t2 == null)
                return true;
            if (t1 == null)
                return false;
            return isSubTree(t1, t2) || checkSubTree(t1.left, t2) || checkSubTree(t1.right, t2);
        }
    
        public boolean isSubTree(TreeNode t1, TreeNode t2){
            if (t2 == null)
                return true;
            if (t1 == null)
                return false;
            if (t1.val != t2.val)
                return false;
            return isSubTree(t1.left,t2.left) && isSubTree(t1.right,t2.right);
        }
    }
    

    
    

    面试题 04.12. 求和路径

    English Version

    题目描述

    给定一棵二叉树,其中每个节点都含有一个整数数值(该值或正或负)。设计一个算法,打印节点数值总和等于某个给定值的所有路径的数量。注意,路径不一定非得从二叉树的根节点或叶节点开始或结束,但是其方向必须向下(只能从父节点指向子节点方向)。

    示例:
    给定如下二叉树,以及目标和 sum = 22

                  5
                 / \
                4   8
               /   / \
              11  13  4
             /  \    / \
            7    2  5   1
    

    返回:

    3
    解释:和为 22 的路径有:[5,4,11,2], [5,8,4,5], [4,11,7]

    提示:

    • 节点总数 <= 10000

    解法

    DFS 深度优先搜索

    Python3

    采用递归的思想,每递归到某个节点时:

    • root.val-sum == 0,结果加 1
    • 考虑将此节点纳入或不纳入路径两种情况

    特殊情况:若此节点的父节点在路径中,此节点必纳入路径(路径不能断)

    class Solution:
        def pathSum(self, root: TreeNode, sum: int) -> int:
            def dfs(root, sum, flag):
                nonlocal ans
                if not root:
                    return 0
                if sum-root.val == 0:
                    ans += 1
                if flag == 0:
                    dfs(root.left, sum, 0)
                    dfs(root.right, sum, 0)
                dfs(root.left, sum-root.val, 1)
                dfs(root.right, sum-root.val, 1)
    
            if not root:
                return 0
            ans = 0
            dfs(root, sum, 0)
            return ans
    

    Java

    使用到 2 个递归过程:

    • BFS(深度优先):(traverse)遍历每个树节点;
    • DFS(广度优先): 从每个树节点出发,节点求和,看是否能满足 sum。

    需要注意,节点值有正有负,需要穷尽所有的可能路径。

    class Solution {
        int ans = 0;
        public int pathSum(TreeNode root, int sum) {
            traverse(root, sum);
            return ans;
        }
    
        void traverse(TreeNode root, int sum) {
            if (root == null) return;
            ans += dfs(root, sum, 0);
            traverse(root.left,  sum);
            traverse(root.right, sum);
        }
    
        // check if sum of path is sum.
        int dfs(TreeNode root, int sum, int cur) {
            if (root == null) return 0;
            cur += root.val;
            int res = 0;
            if (cur == sum) res++;
            res += dfs(root.left,  sum, cur);
            res += dfs(root.right, sum, cur);
            return res;
        }
    }
    

    
    

    面试题 05.01. 插入

    English Version

    题目描述

    插入。给定两个32位的整数NM,以及表示比特位置的ij。编写一种方法,将M插入N,使得M从N的第j位开始,到第i位结束。假定从j位到i位足以容纳M,也即若M = 10 011,那么j和i之间至少可容纳5个位。例如,不可能出现j = 3和i = 2的情况,因为第3位和第2位之间放不下M。

    示例1:

     输入:N = 10000000000, M = 10011, i = 2, j = 6
     输出:N = 10001001100
    

    示例2:

     输入: N = 0, M = 11111, i = 0, j = 4
     输出:N = 11111
    

    解法

    Python3

    
    

    Java

    class Solution {
        public int insertBits(int N, int M, int i, int j) {
            for (int k = i; k <= j; k++) {
                N &= ~(1 << k);
            }
            return N ^ (M << i);
        }
    }
    延伸:
    3.位异或运算(^)
    
    运算规则是:两个数转为二进制,然后从高位开始比较,如果相同则为0,不相同则为1。
    
    比如:8^11.
    
    8转为二进制是100011转为二进制是1011.从高位开始比较得到的是:0011.然后二进制转为十进制,就是Integer.parseInt("0011",2)=3;
    
    4.位与运算符(&)
    
    运算规则:两个数都转为二进制,然后从高位开始比较,如果两个数都为1则为1,否则为0。
    
    比如:129&128.
    
    129转换成二进制就是10000001128转换成二进制就是10000000。从高位开始比较得到,得到10000000,即128.
    
     
    
    5.位或运算符(|)
    
    运算规则:两个数都转为二进制,然后从高位开始比较,两个数只要有一个为1则为1,否则就为0。
    
    比如:129|128.
    
    129转换成二进制就是10000001128转换成二进制就是10000000。从高位开始比较得到,得到10000001,即129.
    
     
    
    6.位非运算符(~)
    
    运算规则:如果位为0,结果是1,如果位为1,结果是0.
    
    比如:~37
    
    在Java中,所有数据的表示方法都是以补码的形式表示,如果没有特殊说明,Java中的数据类型默认是int,int数据类型的长度是8位,一位是四个字节,就是32字节,32bit.
    
    8转为二进制是100101.
    
    补码后为: 00000000 00000000 00000000 00100101
    
    取反为:    11111111 11111111 11111111 11011010
    
    因为高位是1,所以原码为负数,负数的补码是其绝对值的原码取反,末尾再加1。
    
    因此,我们可将这个二进制数的补码进行还原: 首先,末尾减1得反码:11111111 11111111 11111111 11011001 其次,将各位取反得原码:
    
    00000000 00000000 00000000 00100110,此时二进制转原码为38
    
    所以~37 = -38. ```
    
    ### **...**
    
    
    
    <!-- tabs:end -->
    # [面试题 05.06. 整数转换](https://leetcode-cn.com/problems/convert-integer-lcci)
    
    [English Version](/lcci/05.06.Convert%20Integer/README_EN.md)
    
    ## 题目描述
    
    <!-- 这里写题目描述 -->
    <p>整数转换。编写一个函数,确定需要改变几个位才能将整数A转成整数B。</p>
    
    <p> <strong>示例1:</strong></p>
    
    <pre>
    <strong> 输入</strong>:A = 29 (或者0b11101), B = 15(或者0b01111)
    <strong> 输出</strong>:2
    </pre>
    
    <p> <strong>示例2:</strong></p>
    
    <pre>
    <strong> 输入</strong>:A = 1,B = 2
    <strong> 输出</strong>:2
    </pre>
    
    <p> <strong>提示:</strong></p>
    
    <ol>
    <li>A,B范围在[-2147483648, 2147483647]之间</li>
    </ol>
    
    ## 解法
    
    <!-- 这里可写通用的实现逻辑 -->
    
    <!-- tabs:start -->
    
    ### **Python3**
    
    <!-- 这里可写当前语言的特殊实现逻辑 -->
    
    ```python
    
    

    Java

    class Solution {
        public int convertInteger(int A, int B) {
        //bitCount实现的功能是计算一个(byte,short,char,int统一按照int方法计算)int,long类型的数值在二进制下“1”的数量。    
            return Integer.bitCount(A ^ B);
        }
    }
    

    
    

    面试题 05.07. 配对交换

    English Version

    题目描述

    配对交换。编写程序,交换某个整数的奇数位和偶数位,尽量使用较少的指令(也就是说,位0与位1交换,位2与位3交换,以此类推)。

    示例1:

     输入:num = 2(或者0b10)
     输出 1 (或者 0b01)
    

    示例2:

     输入:num = 3
     输出:3
    

    提示:

    1. num的范围在[0, 2^30 - 1]之间,不会发生整数溢出。

    解法

    Python3

    
    

    Java

    class Solution {
        public int exchangeBits(int num) {
            int t1 = num >> 1;
        	int t2 = num << 1;
        	return t1 & 0x55555555 | t2 & 0xaaaaaaaa;
        }
    }
    

    
    

    面试题 08.01. 三步问题

    English Version

    题目描述

    三步问题。有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶或3阶。实现一种方法,计算小孩有多少种上楼梯的方式。结果可能很大,你需要对结果模1000000007。

    示例1:

     输入:n = 3 
     输出:4
     说明: 有四种走法
    

    示例2:

     输入:n = 5
     输出:13
    

    提示:

    1. n范围在[1, 1000000]之间

    解法

    递推法。f(n)=f(n-1)+f(n-2)+f(n-3)

    Python3

    class Solution:
        def waysToStep(self, n: int) -> int:
            if n < 3:
                return n
            a, b, c = 1, 2, 4
            for _ in range(4, n + 1):
                a, b, c = b, c, (a + b + c) % 1000000007
            return c
    

    Java

    class Solution {
        public int waysToStep(int n) {
            if (n < 3) {
                return n;
            }
            int a = 1, b = 2, c = 4;
            for (int i = 4; i <= n; ++i) {
                int t = a;
                a = b;
                b = c;
                c = ((a + b) % 1000000007 + t) % 1000000007;
            }
            return c;
        }
    }
    

    C++

    class Solution {
    public:
        int waysToStep(int n) {
            if (n < 3) {
                return n;
            }
            int a = 1, b = 2, c = 4, i = 4;
            while (i++ <= n) {
                int t = ((a + b) % 1000000007 + c) % 1000000007;
                a = b;
                b = c;
                c = t;
            }
            return c;
        }
    };
    

    面试题 08.09. 括号

    English Version

    题目描述

    括号。设计一种算法,打印n对括号的所有合法的(例如,开闭一一对应)组合。

    说明:解集不能包含重复的子集。

    例如,给出 n = 3,生成结果为:

    [
      "((()))",
      "(()())",
      "(())()",
      "()(())",
      "()()()"
    ]
    

    解法

    Python3

    递归求解。其中,left 表示剩余的 (right 表示剩余的 )

    • left > right 时,说明 state 中 ( 少于 ),不是合法组合,直接剪枝;
    • right == 0 时,说明 state 组合完毕;
    • left > 0 时,此时可往 state 添加一个 (
    • right > 0 时,此时可往 state 添加一个 )
    class Solution:
        def generateParenthesis(self, n: int) -> List[str]:
            res = []
            def generate(state, left, right):
                # 剩余的`(`多于`)`
                if left > right:
                    return
                if right == 0:
                    res.append(state)
                    return
                if left > 0:
                    generate(state + '(', left - 1, right)
                if right > 0:
                    generate(state + ')', left, right - 1)
            generate('', n, n)
            return res
    

    Java

    class Solution {
        List<String> res;
    
        public List<String> generateParenthesis(int n) {
            res = new ArrayList<>();
            generate("", n, n);
            return res;
        }
    
        private void generate(String state, int left, int right) {
            if (left > right) {
                return;
            }
            if (right == 0) {
                res.add(state);
                return;
            }
            if (left > 0) {
                generate(state + "(", left - 1, right);
            }
            if (right > 0) {
                generate(state + ")", left, right - 1);
            }
        }
    }
    

    
    

    面试题 08.10. 颜色填充

    English Version

    题目描述

    颜色填充。编写函数,实现许多图片编辑软件都支持的“颜色填充”功能。给定一个屏幕(以二维数组表示,元素为颜色值)、一个点和一个新的颜色值,将新颜色值填入这个点的周围区域,直到原来的颜色值全都改变。

    示例1:

     输入:
    image = [[1,1,1],[1,1,0],[1,0,1]] 
    sr = 1, sc = 1, newColor = 2
     输出:[[2,2,2],[2,2,0],[2,0,1]]
     解释: 
    在图像的正中间,(坐标(sr,sc)=(1,1)),
    在路径上所有符合条件的像素点的颜色都被更改成2。
    注意,右下角的像素没有更改为2,
    因为它不是在上下左右四个方向上与初始点相连的像素点。
    

    说明:

    1. image 和 image[0] 的长度在范围 [1, 50] 内。
    2. 给出的初始点将满足 0 <= sr < image.length 和 0 <= sc < image[0].length。
    3. image[i][j] 和 newColor 表示的颜色值在范围 [0, 65535]内。

    解法

    Python3

    
    

    Java

    class Solution {
        public int[][] floodFill(int[][] image, int sr, int sc, int newColor) {
            int oldColor = image[sr][sc];
            dfs(image, sr, sc, oldColor, newColor);
            return image;
        }
    
        private void dfs(int[][] image, int sr, int sc, int oldColor, int newColor) {
            if (sr < 0 || sc < 0 || sr >= image.length || sc >= image[0].length) {
                return;
            }
    
            int color = image[sr][sc];
            if (color != newColor && color == oldColor) {
                image[sr][sc] = newColor;
                // up down left right
                dfs(image, sr, sc + 1, oldColor, newColor);
                dfs(image, sr, sc - 1, oldColor, newColor);
                dfs(image, sr + 1, sc, oldColor, newColor);
                dfs(image, sr - 1, sc, oldColor, newColor);
            }
        }
    }
    

    
    

    面试题 10.09. 排序矩阵查找

    English Version

    题目描述

    给定M×N矩阵,每一行、每一列都按升序排列,请编写代码找出某元素。

    示例:

    现有矩阵 matrix 如下:

    [
      [1,   4,  7, 11, 15],
      [2,   5,  8, 12, 19],
      [3,   6,  9, 16, 22],
      [10, 13, 14, 17, 24],
      [18, 21, 23, 26, 30]
    ]
    

    给定 target = 5,返回 true

    给定 target = 20,返回 false

    解法

    从左下角(或右上角)开始查找即可。

    Python3

    class Solution:
        def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
            if not matrix or not matrix[0]:
                return False
            rows, cols = len(matrix), len(matrix[0])
            i, j = rows - 1, 0
            while i >= 0 and j < cols:
                if matrix[i][j] == target:
                    return True
                if matrix[i][j] > target:
                    i -= 1
                else:
                    j += 1
            return False
    
    

    Java

    class Solution {
        public boolean searchMatrix(int[][] matrix, int target) {
            if (matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) {
                return false;
            }
            int rows = matrix.length, cols = matrix[0].length;
            int i = rows - 1, j = 0;
            while (i >= 0 && j < cols) {
                if (matrix[i][j] == target) {
                    return true;
                }
                if (matrix[i][j] > target) {
                    --i;
                } else {
                    ++j;
                }
            }
            return false;
        }
    }
    

    
    

    面试题 16.01. 交换数字

    English Version

    题目描述

    编写一个函数,不用临时变量,直接交换numbers = [a, b]ab的值。

    示例:

    输入: numbers = [1,2]
    输出: [2,1]
    

    提示:

    • numbers.length == 2

    解法

    异或运算。

    Python3

    class Solution:
        def swapNumbers(self, numbers: List[int]) -> List[int]:
            numbers[0], numbers[1] = numbers[1], numbers[0]
            return numbers
    

    Java

    class Solution {
        public int[] swapNumbers(int[] numbers) {
            numbers[0] = numbers[0] ^ numbers[1]; //3
            numbers[1] = numbers[0] ^ numbers[1]; //1
            numbers[0] = numbers[0] ^ numbers[1]; //2
            return numbers;
        }
    }
    

    
    

    面试题 16.06. 最小差

    English Version

    题目描述

    给定两个整数数组ab,计算具有最小差绝对值的一对数值(每个数组中取一个值),并返回该对数值的差

    示例:

    输入:{1, 3, 15, 11, 2}, {23, 127, 235, 19, 8}
    输出: 3,即数值对(11, 8)
    

    提示:

    • 1 <= a.length, b.length <= 100000
    • -2147483648 <= a[i], b[i] <= 2147483647
    • 正确结果在区间[-2147483648, 2147483647]内

    解法

    Python3

    class Solution:
        def smallestDifference(self, a: List[int], b: List[int]) -> int:
            a.sort()
            b.sort()
            i, j, res = 0, 0, 2147483647
            m, n = len(a), len(b)
            while i < m and j < n:
                if a[i] == b[j]: return 0
                res = min(res, abs(a[i] - b[j]))
                if a[i] > b[j]: j += 1
                else: i += 1
            return res
    
    

    Java

    class Solution {
        public int smallestDifference(int[] a, int[] b) {
            Arrays.sort(a);
            Arrays.sort(b);
            int m = a.length, n = b.length;
            int i = 0, j = 0;
            long res = Long.MAX_VALUE;
            while (i < m && j < n) {
                if (a[i] == b[j]) return 0;
                res = Math.min(res, Math.abs((long) a[i] - (long) b[j]));
                if (a[i] > b[j]) ++j;
                else ++i;
            }
            return (int) res;
        }
    }
    

    
    

    面试题 16.10. 生存人数

    English Version

    题目描述

    给定N个人的出生年份和死亡年份,第i个人的出生年份为birth[i],死亡年份为death[i],实现一个方法以计算生存人数最多的年份。

    你可以假设所有人都出生于1900年至2000年(含1900和2000)之间。如果一个人在某一年的任意时期都处于生存状态,那么他们应该被纳入那一年的统计中。例如,生于1908年、死于1909年的人应当被列入1908年和1909年的计数。

    如果有多个年份生存人数相同且均为最大值,输出其中最小的年份。

    示例:

    输入:
    birth = {1900, 1901, 1950}
    death = {1948, 1951, 2000}
    输出: 1901
    

    提示:

    • 0 < birth.length == death.length <= 10000
    • birth[i] <= death[i]

    解法

    Python3

    class Solution:
        def maxAliveYear(self, birth: List[int], death: List[int]) -> int:
            years = [0] * 101
            for i in range(len(birth)):
                start = birth[i] - 1900
                end = death[i] - 1900
                for j in range(start, end + 1):
                    years[j] += 1
            max_v = years[0]
            res = 0
            for i in range(1, 101):
                if years[i] > max_v:
                    max_v = years[i]
                    res = i
            return 1900 + res
    

    Java

    class Solution {
        public int maxAliveYear(int[] birth, int[] death) {
            int[] years = new int[101];
            int n = birth.length;
            for (int i = 0; i < n; ++i) {
                int start = birth[i] - 1900;
                int end = death[i] - 1900;
                for (int j = start; j <= end; ++j) {
                    ++years[j];
                }
            }
            int max = years[0];
            int res = 0;
            for (int i = 1; i < 101; ++i) {
                if (years[i] > max) {
                    max = years[i];
                    res = i;
                }
            }
            return 1900 + res;
        }
    }
    

    
    

    面试题 16.11. 跳水板

    English Version

    题目描述

    你正在使用一堆木板建造跳水板。有两种类型的木板,其中长度较短的木板长度为shorter,长度较长的木板长度为longer。你必须正好使用k块木板。编写一个方法,生成跳水板所有可能的长度。

    返回的长度需要从小到大排列。

    示例:

    输入:
    shorter = 1
    longer = 2
    k = 3
    输出: {3,4,5,6}
    

    提示:

    • 0 < shorter <= longer
    • 0 <= k <= 100000

    解法

    Python3

    
    

    Java

    class Solution {
        public int[] divingBoard(int shorter, int longer, int k) {
            if (k == 0) {
                return new int[0];
            }
            if (longer == shorter) {
                return new int[]{longer * k};
            }
            int[] ans = new int[k + 1];
            for (int i = 0;i <= k;i++) {
                ans[i] = longer * i + shorter * (k - i);
            }
            return ans;
        }
    }
    

    
    

    面试题 16.21. 交换和

    English Version

    题目描述

    给定两个整数数组,请交换一对数值(每个数组中取一个数值),使得两个数组所有元素的和相等。

    返回一个数组,第一个元素是第一个数组中要交换的元素,第二个元素是第二个数组中要交换的元素。若有多个答案,返回任意一个均可。若无满足条件的数值,返回空数组。

    示例:

    输入: array1 = [4, 1, 2, 1, 1, 2], array2 = [3, 6, 3, 3]
    输出: [1, 3]
    

    示例:

    输入: array1 = [1, 2, 3], array2 = [4, 5, 6]
    输出: []

    提示:

    • 1 <= array1.length, array2.length <= 100000

    解法

    先计算两个数组的差值 diff,若 diff 为奇数,则说明无满足条件的数值,返回空数组。否则,将 array2 转为 set。然后遍历 array1 中的每个数 e,若值 e - diffset 中,则说明找到满足条件的数值对。

    Python3

    class Solution:
        def findSwapValues(self, array1: List[int], array2: List[int]) -> List[int]:
            diff = sum(array1) - sum(array2)
            if diff & 1: return []
            diff >>= 1
            s = set(array2)
            for e in array1:
                if (e - diff) in s: return [e, e - diff]
            return []
    

    Java

    class Solution {
        public int[] findSwapValues(int[] array1, int[] array2) {
            int diff = sum(array1) - sum(array2);
            if ((diff & 1) == 1) {
                return new int[]{};
            }
            diff >>= 1;
            Set<Integer> s = Arrays.stream(array2).boxed().collect(Collectors.toSet());
            for (int e : array1) {
                if (s.contains((e - diff))) {
                    return new int[]{e, e - diff};
                }
            }
            return new int[]{};
        }
    
        private int sum(int[] array) {
            int res = 0;
            for (int e : array) {
                res += e;
            }
            return res;
        }
    }s
    

    
    

    面试题 17.01. 不用加号的加法

    English Version

    题目描述

    设计一个函数把两个数字相加。不得使用 + 或者其他算术运算符。

    示例:

    输入: a = 1, b = 1
    输出: 2

     

    提示:

    • ab 均可能是负数或 0
    • 结果不会溢出 32 位整数

    解法

    Python3

    
    

    Java

    class Solution {
        public int add(int a, int b) {
            int sum = 0, carry = 0;
            while (b != 0) {
                sum = a ^ b;
                carry = (a & b) << 1;
                a = sum;
                b = carry;
            }
            return a;
        }
    }
    

    
    

    面试题 17.04. 消失的数字

    English Version

    题目描述

    数组nums包含从0n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?

    注意:本题相对书上原题稍作改动

    示例 1:

    输入:[3,0,1]
    输出:2

     

    示例 2:

    输入:[9,6,4,2,3,5,7,0,1]
    输出:8
    

    解法

    利用异或的特性,res = res ^ x ^ x。对同一个值异或两次,结果等于它本身。最后异或的结果,就是只出现一次的数字,即数组中缺失的整数。

    Python3

    class Solution:
        def missingNumber(self, nums: List[int]) -> int:
            res = 0
            for i, num in enumerate(nums):
                res ^= i
                res ^= num
            res ^= len(nums)
            return res
    

    Java

    class Solution {
        public int missingNumber(int[] nums) {
            int res = 0, n = nums.length;
            for (int i = 0; i < n; ++i) {
                res ^= i;
                res ^= nums[i];
            }
            res ^= n;
            return res;
        }
    }
    

    
    

    面试题 17.12. BiNode

    English Version

    题目描述

    二叉树数据结构TreeNode可用来表示单向链表(其中left置空,right为下一个链表节点)。实现一个方法,把二叉搜索树转换为单向链表,要求值的顺序保持不变,转换操作应是原址的,也就是在原始的二叉搜索树上直接修改。

    返回转换后的单向链表的头节点。

    注意:本题相对原题稍作改动

     

    示例:

    输入: [4,2,5,1,3,null,6,0]
    输出: [0,null,1,null,2,null,3,null,4,null,5,null,6]
    

    提示:

    • 节点数量不会超过 100000。

    解法

    递归将左子树、右子树转换为左、右链表 left 和 right。然后将左链表 left 的最后一个结点的 right 指针指向 root,root 的 right 指针指向右链表 right,并将 root 的 left 指针值为空。

    897. 递增顺序查找树

    Python3

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def convertBiNode(self, root: TreeNode) -> TreeNode:
            if root is None:
                return None
            left = self.convertBiNode(root.left)
            right = self.convertBiNode(root.right)
            if left is None:
                root.right = right
                return root
            res = left
            while left and left.right:
                left = left.right
            left.right = root
            root.right = right
            root.left = None
            return res
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public TreeNode convertBiNode(TreeNode root) {
            if (root == null) return null;
            TreeNode left = convertBiNode(root.left);
            TreeNode right = convertBiNode(root.right);
            if (left == null) {
                root.right = right;
                return root;
            }
            TreeNode res = left;
            while (left != null && left.right != null) {
                left = left.right;
            }
            left.right = root;
            root.right = right;
            root.left = null;
            return res;
        }
    }
    

    
    

    面试题 17.13. 恢复空格

    English Version

    题目描述

    哦,不!你不小心把一个长篇文章中的空格、标点都删掉了,并且大写也弄成了小写。像句子"I reset the computer. It still didn’t boot!"已经变成了"iresetthecomputeritstilldidntboot"。在处理标点符号和大小写之前,你得先把它断成词语。当然了,你有一本厚厚的词典dictionary,不过,有些词没在词典里。假设文章用sentence表示,设计一个算法,把文章断开,要求未识别的字符最少,返回未识别的字符数。

    注意:本题相对原题稍作改动,只需返回未识别的字符数

     

    示例:

    输入:
    dictionary = ["looked","just","like","her","brother"]
    sentence = "jesslookedjustliketimherbrother"
    输出: 7
    解释: 断句后为"jess looked just like tim her brother",共7个未识别字符。
    

    提示:

    • 0 <= len(sentence) <= 1000
    • dictionary中总字符数不超过 150000。
    • 你可以认为dictionarysentence中只包含小写字母。

    解法

    Python3

    
    

    Java

    class Solution {
        public int respace(String[] dictionary, String sentence) {
            Set<String> set = new HashSet<>(dictionary.length);
            set.addAll(Arrays.asList(dictionary));
    
            int[] dp = new int[sentence.length() + 1];
            for (int i = 1; i <= sentence.length(); i++) {
                dp[i] = dp[i - 1] + 1;
                for (int j = 0;j < i;j++) {
                    if (set.contains(sentence.substring(j, i))) {
                         dp[i] = Math.min(dp[i], dp[j]);
                    }
                }
            }
            return dp[sentence.length()];
        }
    }
    

    
    

    面试题 17.19. 消失的两个数字

    English Version

    题目描述

    给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗?

    以任意顺序返回这两个数字均可。

    示例 1:

    输入: [1]
    输出: [2,3]

    示例 2:

    输入: [2,3]
    输出: [1,4]

    提示:

    • nums.length <= 30000

    解法

    异或运算。与面试题 56 - I. 数组中数字出现的次数 类似。

    Python3

    class Solution:
        def missingTwo(self, nums: List[int]) -> List[int]:
            res, n = 0, len(nums)
            for i in range(n):
                res ^= nums[i]
                res ^= (i + 1)
            res ^= (n + 1)
            res ^= (n + 2)
            pos = 0
            while (res & 1) == 0:
                pos += 1
                res >>= 1
    
            a = b = 0
            for num in nums:
                t = num >> pos
                if (t & 1) == 0:
                    a ^= num
                else:
                    b ^= num
    
            for i in range(1, n + 3):
                t = i >> pos
                if (t & 1) == 0:
                    a ^= i
                else:
                    b ^= i
            return [a, b]
    

    Java

    class Solution {
        public int[] missingTwo(int[] nums) {
            int res = 0, n = nums.length;
            for (int i = 0; i < n; ++i) {
                res ^= nums[i];
                res ^= (i + 1);
            }
            res ^= (n + 1);
            res ^= (n + 2);
    
            int pos = 0;
            while ((res & 1) == 0) {
                pos += 1;
                res >>= 1;
            }
    
            int a = 0, b = 0;
            for (int num : nums) {
                int t = num >> pos;
                if ((t & 1) == 0) {
                    a ^= num;
                } else {
                    b ^= num;
                }
            }
            for (int i = 1; i <= n + 2; ++i) {
                int t = i >> pos;
                if ((t & 1) == 0) {
                    a ^= i;
                } else {
                    b ^= i;
                }
            }
            return new int[]{a, b};
        }
    }
    

    
    

    面试题 17.20. 连续中值

    English Version

    题目描述

    随机产生数字并传递给一个方法。你能否完成这个方法,在每次产生新值时,寻找当前所有值的中间值(中位数)并保存。

    中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。

    例如,

    [2,3,4] 的中位数是 3

    [2,3] 的中位数是 (2 + 3) / 2 = 2.5

    设计一个支持以下两种操作的数据结构:

    • void addNum(int num) - 从数据流中添加一个整数到数据结构中。
    • double findMedian() - 返回目前所有元素的中位数。

    示例:

    addNum(1)
    addNum(2)
    findMedian() -> 1.5
    addNum(3) 
    findMedian() -> 2
    

    解法

    • 创建大根堆、小根堆,其中:大根堆存放较小的一半元素,小根堆存放较大的一半元素。
    • 添加元素时,若两堆元素个数相等,放入小根堆(使得小根堆个数多 1);若不等,放入大根堆(使得大小根堆元素个数相等)
    • 取中位数时,若两堆元素个数相等,取两堆顶求平均值;若不等,取小根堆堆顶。

    Python3

    class MedianFinder:
    
        def __init__(self):
            """
            initialize your data structure here.
            """
            self.max_heap = []
            self.min_heap = []
    
    
        def addNum(self, num: int) -> None:
            if len(self.max_heap) == len(self.min_heap):
                heapq.heappush(self.min_heap, -heapq.heappushpop(self.max_heap, -num))
            else:
                heapq.heappush(self.max_heap, -heapq.heappushpop(self.min_heap, num))
    
        def findMedian(self) -> float:
            return (-self.max_heap[0] + self.min_heap[0]) / 2 if len(self.max_heap) == len(self.min_heap) else self.min_heap[0]
    
    
    # Your MedianFinder object will be instantiated and called as such:
    # obj = MedianFinder()
    # obj.addNum(num)
    # param_2 = obj.findMedian()
    

    Java

    class MedianFinder {
        private Queue<Integer> minHeap;
        private Queue<Integer> maxHeap;
    
        /** initialize your data structure here. */
        public MedianFinder() {
            //PriorityQueue是基于优先堆的一个无界队列,这个优先队列中的元素可以默认自然排序或者通过提供的Comparator(比较器)在队列实例化的时排序。    
            minHeap = new PriorityQueue<>();
            maxHeap = new PriorityQueue<>((a, b) -> b - a);
        }
    
        public void addNum(int num) {
            if (minHeap.size() == maxHeap.size()) {
                maxHeap.offer(num);
                minHeap.offer(maxHeap.poll());
            } else {
                minHeap.offer(num);
                maxHeap.offer(minHeap.poll());
            }
        }
    
        public double findMedian() {
            return minHeap.size() == maxHeap.size() ? (minHeap.peek() + maxHeap.peek()) / 2.0 : minHeap.peek();
        }
    }
    
    /**
     * Your MedianFinder object will be instantiated and called as such:
     * MedianFinder obj = new MedianFinder();
     * obj.addNum(num);
     * double param_2 = obj.findMedian();
     */
    

    
    
    • 0
      点赞
    • 1
      收藏
      觉得还不错? 一键收藏
    • 1
      评论
    评论 1
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值