喜刷刷3
[LeetCode#413] Arithmetic Slices 算数切片 A sequence of number is called arithmetic if it consists of at least three elements and if the difference between any two consecutive elements is the same. For example, these are arithmetic sequence: 1, 3, 5, 7, 9 7, 7, 7, 7 3, -1, -5, -9 The following sequence is not arithmetic. 1, 1, 2, 5, 7 A zero-indexed array A consisting of N numbers is given. A slice of that array is any pair of integers (P, Q) such that 0 <= P < Q < N. A slice (P, Q) of array A is called arithmetic if the sequence: A[P], A[p + 1], ..., A[Q - 1], A[Q] is arithmetic. In particular, this means that P + 1 < Q. The function should return the number of arithmetic slices in the array A. Example: A = [1, 2, 3, 4] return: 3, for 3 arithmetic slices in A: [1, 2, 3], [2, 3, 4] and [1, 2, 3, 4] itself.
Arithmetic是等差数列,限定了等差数列的长度至少为3。 [Mine]一个数列中可能有多个不同的等差数列,这里要找所有大于3的等差数列的切片数之和 定义一个一维dp数组,其中dp[i]表示,到i位置为止的算数切片的个数,那么我们从第三个数字开始遍历,如果当前数字和之前两个数字构成算数切片,那么我们更新dp[i]为dp[i-1]+1,然后res累加上dp[i]的值 可以用一个变量替代DP数组 [Mine]DP[i]是到i位置为止的切片个数,之前到i-1的切片都可以直接算到i中,成为长度大于3的切片,然后加上唯一一个长度等于3的切片:i-2, i-1, i。这就是dp[i]=dp[i-1]+1 [Mine]感觉有问题啊,只计算了,(123),(234),没有算(1234)?????
[LeetCode#410] Split Array Largest Sum 分割数组的最大值 Given an array which consists of non-negative integers and an integer m, you can split the array into m non-empty continuous subarrays. Write an algorithm to minimize the largest sum among these m subarrays. Note: Given m satisfies the following constraint: 1 ≤ m ≤ length(nums) ≤ 14,000. Examples: Input: nums = [7,2,5,10,8] m = 2 Output: 18 Explanation: There are four ways to split nums into two subarrays. The best way is to split it into [7,2,5] and [10,8], where the largest sum among the two subarrays is only 18.
# 二分搜索法 如果m和数组nums的个数相等,那么每个数组都是一个子数组,所以返回nums中最大的数字即可,如果m为1,那么整个nums数组就是一个子数组,返回nums所有数字之和,所以对于其他有效的m值,返回的值必定在上面两个值之间,所以我们可以用二分搜索法来做。 接下来要做的是找出,和最大,且小于等于mid的子数组的个数(由于子数组要保证连续,所以简单的贪婪法即可),如果子数组个数小于m,说明mid大了,如果大于m,说明mid小了。这样不断调试mid,找出子数组个数等于m的mid最小值。 [Mine]把"给定划分组数,找最大sum最小"问题,转化成"给定最大sum,找最少划分组数",用逼近给定划分组数的方法,二分调整对最大sum的最小值猜测。 #2 DP 建立一个二维数组dp,其中dp[i][j]表示将数组中前j个数字分成i组所能得到的最小的各个子数组中最大值,初始化为整型最大值。为了能快速的算出子数组之和,我们还是要建立累计和数组 如果前j个数字要分成i组,那么i的范围是[1, j],所以我们要遍历这中间所有的情况,假如中间任意一个位置k,dp[i-1][k]表示数组中前k个数字分成i-1组所能得到的最小的各个子数组中最大值,而sums[j]-sums[k]就是后面的数字之和,我们取二者之间的较大值,然后和dp[i][j]原有值进行对比,更新dp[i][j]为二者之中的较小值,这样k在[1, j]的范围内扫过一遍,dp[i][j]就能更新到最小值,我们最终返回dp[m][n]即可 分割重现关系(Partition Recurrence Relation),用式子表示是T(i, j) = T(i, m) + T(m+1, j) + C。这里的C就是处理合并两个部分的子问题 for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { for (int k = i - 1; k < j; ++k) { int val = max(dp[i - 1][k], sums[j] - sums[k]); dp[i][j] = min(dp[i][j], val); } } } return dp[m][n]; [Mine]最终结果depend on上一次划分,上一次划分是在更短的字符串和更少的划分次数上。 最简单的一次划分是用累加和解决的
[LeetCode#504] Base 7 基数七 Given an integer, return its base 7 string representation. Example 1: Input: 100 Output: "202" Example 2: Input: -7 Output: "-10" Note: The input will be in range of [-1e7, 1e7].
# 迭代 # 递归 string convertToBase7(int num) { if (num < 0) return "-" + convertToBase7(-num); if (num < 7) return to_string(num); return convertToBase7(num / 7) + to_string(num % 7); }
[LeetCode#494] Target Sum 目标和 You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols + and -. For each integer, you should choose one from + and - as its new symbol. Find out how many ways to assign symbols to make sum of integers equal to target S. Example 1: Input: nums is [1, 1, 1, 1, 1], S is 3. Output: 5 Explanation: -1+1+1+1+1 = 3 +1-1+1+1+1 = 3 +1+1-1+1+1 = 3 +1+1+1-1+1 = 3 +1+1+1+1-1 = 3 There are 5 ways to assign symbols to make the sum of nums be target 3. Note: The length of the given array is positive and will not exceed 20. The sum of elements in the given array will not exceed 1000. Your output answer is guaranteed to be fitted in a 32-bit integer.
#1 DSF 在递归函数中,分别对目标值进行加上当前数字调用递归,和减去当前数字调用递归,这样会涵盖所有情况,并且当所有数字遍历完成后,我们看若目标值为0了,则结果res自增1 #2 DSF + memory [Mine] #2应该最容易想到 #3 DP dp[i][j]表示到第i-1个数字且和为j的情况总数 HashMap<Integer, Integer> dp[n]; sum = dp[i].key, cnt=dp[i].getValue(sum); cnt2 = dp[i+1].getValue(sum +- num[i]) + cnt dp[i+1].put(sum +- num[i], cnt2) return dp[n].getValue(targetSum) #4 DP + 空间优化 只用一个哈希表,而不是用一个数组的哈希表,我们在遍历数组中的每一个数字时,新建一个哈希表,我们在遍历原哈希表中的项时更新这个新建的哈希表,最后把新建的哈希表整个赋值和原哈希表 [Mine]一维哈希表数组降为一个哈希表 #5 DP, 0-1 knapsack (花花酱 LeetCode 494. Target Sum 下 - 刷题找工作 EP157) input scope: -sum(n)~+sum(n); if offset the input: 0~2*sum(n), new target is sum(n)+target; then half input:0~sum(n), new target is (sum(n)+target)/2; now it is 0-1 knapsack
[LeetCode#441] Arranging Coins 排列硬币 You have a total of n coins that you want to form in a staircase shape, where every k-th row must have exactly k coins. Given n, find the total number of full staircase rows that can be formed. n is a non-negative integer and fits within the range of a 32-bit signed integer. Example 1: n = 5 The coins can form the following rows: ¤ ¤ ¤ ¤ ¤ Because the 3rd row is incomplete, we return 2. Example 2: n = 8 The coins can form the following rows: ¤ ¤ ¤ ¤ ¤ ¤ ¤ ¤ Because the 4th row is incomplete, we return 3.
#1 O(n) 从第一行开始,一行一行的从n中减去,如果此时剩余的硬币没法满足下一行需要的硬币数了,我们之间返回当前行数即可 #2 O(lgn) 二分搜索法,我们搜索前i行之和刚好大于n的临界点,这样我们减一个就是能排满的行数 sum_i = (1 + i) * i / 2 #1 O(1) x = (-1 + sqrt(8 * n + 1)) / 2, 然后取整后就是能填满的行数
[LeetCode#418] Sentence Screen Fitting 调整屏幕上的句子 Given a rows x cols screen and a sentence represented by a list of words, find how many times the given sentence can be fitted on the screen. Note: A word cannot be split into two lines. The order of words in the sentence must remain unchanged. Two consecutive words in a line must be separated by a single space. Total words in the sentence won't exceed 100. Length of each word won't exceed 10. 1 ≤ rows, cols ≤ 20,000. Example 1: Input: rows = 2, cols = 8, sentence = ["hello", "world"] Output: 1 Explanation: hello--- world--- The character '-' signifies an empty space on the screen. Example 2: Input: rows = 3, cols = 6, sentence = ["a", "bcd", "e"] Output: 2 Explanation: a-bcd- e-a--- bcd-e- The character '-' signifies an empty space on the screen. Example 3: Input: rows = 4, cols = 5, sentence = ["I", "had", "apple", "pie"] Output: 1 Explanation: I-had apple pie-I had-- The character '-' signifies an empty space on the screen.
#1 [Mine] ?????? #2 需要统计加空格的句子总长度,然后遍历每一行,初始化colsRemaining为cols,然后还需要一个变量idx,来记录当前单词的位置,如果colsRemaining大于0,就进行while循环,如果当前单词的长度小于等于colsRemaining,说明可以放下该单词,那么就减去该单词的长度就是剩余的空间,然后如果此时colsRemaining仍然大于0,则减去空格的长度1,然后idx自增1,如果idx此时超过单词个数的范围了,说明一整句可以放下,那么就有可能出现宽度远大于句子长度的情况,所以我们加上之前放好的一句之外,还要加上colsRemaining/len的个数,然后colsRemaining%len是剩余的位置,此时idx重置为0 [Mine]是否需要某种方法找到循环字段?
[LeetCode#480] Sliding Window Median 滑动窗口中位数 Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value. Examples: [2,3,4] , the median is 3 [2,3], the median is (2 + 3) / 2 = 2.5 Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Your job is to output the median array for each window in the original array. For example, Given nums = [1,3,-1,-3,5,3,6,7], and k = 3. Window position Median --------------- ----- [1 3 -1] -3 5 3 6 7 1 1 [3 -1 -3] 5 3 6 7 -1 1 3 [-1 -3 5] 3 6 7 -1 1 3 -1 [-3 5 3] 6 7 3 1 3 -1 -3 [5 3 6] 7 5 1 3 -1 -3 5 [3 6 7] 6 Therefore, return the median sliding window as [1,-1,-1,3,5,6]. Note: You may assume k is always valid, ie: 1 ≤ k ≤ input array's size for non-empty array.
#1 multiset #2 similar to #295 Find Median from Data Stream 维护了small和large两个堆,分别保存有序数组的左半段和右半段的数字
[LeetCode#476] Number Complement 补数 Given a positive integer, output its complement number. The complement strategy is to flip the bits of its binary representation. Note: The given integer is guaranteed to fit within the range of a 32-bit signed integer. You could assume no leading zero bit in the integer's binary representation. Example 1: Input: 5 Output: 2 Explanation: The binary representation of 5 is 101 (no leading zero bits), and its complement is 010. So you need to output 2. Example 2: Input: 1 Output: 0 Explanation: The binary representation of 1 is 1 (no leading zero bits), and its complement is 0. So you need to output 0.
#1 从高往低遍历,如果遇到第一个1了后,我们的flag就赋值为true,然后就可以进行翻转了,翻转的方法就是对应位异或一个1即可 #2 只要用一个mask来标记最高位1前面的所有0的位置,然后对mask取反后,与上对num取反的结果即可 int mask = INT_MAX; while (mask & num) mask <<= 1; return ~mask & ~num;
[LeetCode#513] Find Bottom Left Tree Value 寻找最左下树结点的值 Given a binary tree, find the leftmost value in the last row of the tree. Example 1: Input: 2 / \ 1 3 Output: 1 Example 2: Input: 1 / \ 2 3 / / \ 4 5 6 / 7 Output: 7 Note: You may assume the tree (i.e., the given root node) is not NULL.
#1 先序遍历遍历的顺序是根-左-右,所以每一行最左边的结点肯定最先遍历到,那么由于是新一行,那么当前深度肯定比之前的最大深度大,所以我们可以更新最大深度为当前深度,结点值res为当前结点值 [Mine]先序遍历,同时记录深度,当深度增长时,当前节点就是当前深度最左节点 #2 层序遍历时遍历完当前行所有结点之后才去下一行,那么我们再遍历每行第一个结点时更新结果res即可,根本不用维护最大深度了
[LeetCode#501] Find Mode in Binary Search Tree 找二分搜索数的众数 Given a binary search tree (BST) with duplicates, find all the mode(s) (the most frequently occurred element) in the given BST. Assume a BST is defined as follows: The left subtree of a node contains only nodes with keys less than or equal to the node's key. The right subtree of a node contains only nodes with keys greater than or equal to the node's key. Both the left and right subtrees must also be binary search trees. For example: Given BST [1,null,2,2], 1 \ 2 / 2 return [2]. Note: If a tree has more than one mode, you can return them in any order. Follow up: Could you do that without using any extra space? (Assume that the implicit stack space incurred due to recursion does not count).
#1 利用一个哈希表来记录数字和其出现次数之前的映射,然后维护一个变量mx来记录当前最多的次数值,这样在遍历完树之后,根据这个mx值就能把对应的元素找出来。那么用这种方法的话就不需要用到二分搜索树的性质了,随意一种遍历方式都可以 #2 由于是二分搜索树,那么我们中序遍历出来的结果就是有序的,这样我们只要比较前后两个元素是否相等,就等统计出现某个元素出现的次数,因为相同的元素肯定是都在一起的
[LeetCode#419] Battleships in a Board 平板上的战船 Given an 2D board, count how many different battleships are in it. The battleships are represented with 'X's, empty slots are represented with '.'s. You may assume the following rules: You receive a valid board, made of only battleships or empty slots. Battleships can only be placed horizontally or vertically. In other words, they can only be made of the shape 1xN (1 row, N columns) or Nx1 (N rows, 1 column), where N can be of any size. At least one horizontal or vertical cell separates between two battleships - there are no adjacent battleships. Example: X..X ...X ...X In the above board there are 2 battleships. Invalid Example: ...X XXXX ...X This is not a valid board - as battleships will always have a cell separating between them. Your algorithm should not modify the value of the board.
#1 只需要遍历一次二维数组就行了,只要找出战舰的起始点。所谓的战舰起始点,就是为X的点,而且该点的上方和左边的点不能为X,所以我们只要找出所有满足这个条件的点即可 #2 DFS or BFS ,既然没有相邻的战舰,那就寻找连续的点就行了
[LeetCode#496] Next Greater Element I 下一个较大的元素之一 You are given two arrays (without duplicates) nums1 and nums2 where nums1's elements are subset of nums2. Find all the next greater numbers for nums1's elements in the corresponding places of nums2. The Next Greater Number of a number x in nums1 is the first greater number to its right in nums2. If it does not exist, output -1 for this number. Example 1: Input: nums1 = [4,1,2], nums2 = [1,3,4,2]. Output: [-1,3,-1] Explanation: For number 4 in the first array, you cannot find the next greater number for it in the second array, so output -1. For number 1 in the first array, the next greater number for it in the second array is 3. For number 2 in the first array, there is no next greater number for it in the second array, so output -1. Example 2: Input: nums1 = [2,4], nums2 = [1,2,3,4]. Output: [3,-1] Explanation: For number 2 in the first array, the next greater number for it in the second array is 3. For number 4 in the first array, there is no next greater number for it in the second array, so output -1. Note: All elements in nums1 and nums2 are unique. The length of both nums1 and nums2 would not exceed 1000.
#1 哈希表先来建立每个数字和其坐标位置之间的映射,那么我们在遍历子集合中的数字时,就能直接定位到该数字在原数组中的位置,然后再往右边遍历寻找较大数即可 #2 哈希表和栈 从前到后遍历原数组中的所有数字,如果此时栈不为空,且栈顶元素小于当前数字,说明当前数字就是栈顶元素的右边第一个较大数,那么建立二者的映射,并且去除当前栈顶元素,最后将当前遍历到的数字压入栈
[LeetCode#454] 4Sum II 四数之和之二 Given four lists A, B, C, D of integer values, compute how many tuples (i, j, k, l) there are such that A[i] + B[j] + C[k] + D[l] is zero. To make problem a bit easier, all A, B, C, D have same length of N where 0 ≤ N ≤ 500. All integers are in the range of -228 to 228 - 1 and the result is guaranteed to be at most 231 - 1. Example: Input: A = [ 1, 2] B = [-2,-1] C = [-1, 2] D = [ 0, 2] Output: 2 Explanation: The two tuples are: 1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0 2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0
#1 如果把A和B的两两之和都求出来,在哈希表中建立两数之和跟其出现次数之间的映射,那么我们再遍历C和D中任意两个数之和,我们只要看哈希表存不存在这两数之和的相反数就行了 #2 两个哈希表分别记录AB和CD的两两之和出现次数,然后遍历其中一个哈希表,并在另一个哈希表中找和的相反数出现的次数 for (auto a : m1) res += a.second * m2[-a.first];
[LeetCode#461] Hamming Distance 汉明距离 The Hamming distance between two integers is the number of positions at which the corresponding bits are different. Given two integers x and y, calculate the Hamming distance. Note: 0 ≤ x, y < 231. Example: Input: x = 1, y = 4 Output: 2 Explanation: 1 (0 0 0 1) 4 (0 1 0 0) ↑ ↑ The above arrows point to positions where the corresponding bits are different.
#1 按位分别取出两个数对应位上的数并异或 #2 直接将两个数字异或起来,然后我们遍历异或结果的每一位,统计为1的个数 #3 num & (num - 1)可以快速地移除最右边的bit 1, 一直循环到num为0, 总的循环数就是num中bit 1的个数
[LeetCode#405] Convert a Number to Hexadecimal 数字转为十六进制 Given an integer, write an algorithm to convert it to hexadecimal. For negative integer, two's complement method is used. Note: All letters in hexadecimal (a-f) must be in lowercase. The hexadecimal string must not contain extra leading 0s. If the number is zero, it is represented by a single zero character '0'; otherwise, the first character in the hexadecimal string will not be the zero character. The given number is guaranteed to fit within the range of a 32-bit signed integer. You must not use any method provided by the library which converts/formats the number to hex directly. Example 1: Input: 26 Output: "1a" Example 2: Input: -1 Output: "ffffffff"
#1 数字范围就是0到UINT_MAX,即为16^8-1,那么最高位就是16^7,我们首先除以这个数字,如果商大于等于10,我们用字母代替,否则就是用数字代替,然后对其余数进行同样的处理,一直到当前数字为0停止,最后我们还要补齐末尾的0 #2 位操作的思路,每次取出最右边四位,如果其大于等于10,找到对应的字母加入结果,反之则将对应的数字加入结果,然后num像右平移四位,循环停止的条件是num为0,或者是已经循环了7次
[LeetCode#503] Next Greater Element II 下一个较大的元素之二 Given a circular array (the next element of the last element is the first element of the array), print the Next Greater Number for every element. The Next Greater Number of a number x is the first greater number to its traversing-order next in the array, which means you could search circularly to find its next greater number. If it doesn't exist, output -1 for this number. Example 1: Input: [1,2,1] Output: [2,-1,2] Explanation: The first 1's next greater number is 2; The number 2 can't find next greater number; The second 1's next greater number needs to search circularly, which is also 2. Note: The length of given array won't exceed 10000.
#1 暴力搜索 O(N^2) #2 栈 O(N) 我们遍历两倍的数组,然后还是坐标i对n取余,取出数字,如果此时栈不为空,且栈顶元素小于当前数字,说明当前数字就是栈顶元素的右边第一个较大数,那么建立二者的映射,并且去除当前栈顶元素,最后如果i小于n,则把i压入栈。因为res的长度必须是n,超过n的部分我们只是为了给之前栈中的数字找较大值,所以不能压入栈, [Mine]从前向后遍历,栈里只保存当前数之前,比它大的数,因为小的数都以当前数为答案,出栈了
[LeetCode#445] Add Two Numbers II 两个数字相加之二 You are given two linked lists representing two non-negative numbers. The most significant digit comes first and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. You may assume the two numbers do not contain any leading zero, except the number 0 itself. Follow up: What if you cannot modify the input lists? In other words, reversing the lists is not allowed. Example: Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 8 -> 0 -> 7
#1 栈 #2 递归 #3 由左到右,不断寻找要计算的位和可能被进位的位
[LeetCode#481] Magical String 神奇字符串 A magical string S consists of only '1' and '2' and obeys the following rules: The string S is magical because concatenating the number of contiguous occurrences of characters '1' and '2' generates the string S itself. The first few elements of string S is the following: S = "1221121221221121122......" If we group the consecutive '1's and '2's in S, it will be: 1 22 11 2 1 22 1 22 11 2 11 22 ...... and the occurrences of '1's or '2's in each group are: 1 2 2 1 1 2 1 2 2 1 2 2 ...... You can see that the occurrence sequence above is the S itself. Given an integer N as input, return the number of '1's in the first N number in the magical string S. Note: N will not exceed 100,000. Example 1: Input: 6 Output: 3 Explanation: The first 6 elements of magical string S is "12211" and it contains three 1's, so return 3.
#1 根据第三个数字2开始往后生成数字,此时生成两个1,然后根据第四个数字1,生成一个2,再根据第五个数字1,生成一个1,以此类推,生成的数字1或2可能通过异或3来交替生成,在生成的过程中同时统计1的个数即可 #2 string s = "122"; int i = 2; while (s.size() < n) { s += string(s[i++] - '0', s.back() ^ 3); } return count(s.begin(), s.begin() + n, '1');
[LeetCode#403] Frog Jump 青蛙过河 A frog is crossing a river. The river is divided into x units and at each unit there may or may not exist a stone. The frog can jump on a stone, but it must not jump into the water. Given a list of stones' positions (in units) in sorted ascending order, determine if the frog is able to cross the river by landing on the last stone. Initially, the frog is on the first stone and assume the first jump must be 1 unit. If the frog's last jump was k units, then its next jump must be either k - 1, k, or k + 1 units. Note that the frog can only jump in the forward direction. Note: The number of stones is ≥ 2 and is < 1,100. Each stone's position will be a non-negative integer < 231. The first stone's position is always 0. Example 1: [0,1,3,5,6,8,12,17] There are a total of 8 stones. The first stone at the 0th unit, second stone at the 1st unit, third stone at the 3rd unit, and so on... The last stone at the 17th unit. Return true. The frog can jump to the last stone by jumping 1 unit to the 2nd stone, then 2 units to the 3rd stone, then 2 units to the 4th stone, then 3 units to the 6th stone, 4 units to the 7th stone, and 5 units to the 8th stone. Example 2: [0,1,2,3,4,8,9,11] Return false. There is no way to jump to the last stone as the gap between the 5th and 6th stone is too large.
#1 递归 以位置和跳跃能力为key(key = pos | jump << 11),遍历每个位置可能得到测跳跃能力。 [Mine]对可能跳到的石头和跳跃力进行递归推进,如果最终可以到对岸,递归返回true,中间任何其他情况,要么skip,要么返回false 用一个哈希表来建立每个石头和在该位置上能获得的弹跳力集合(与起跳点的距离)之间的映射,并且建立一个一维maxJump数组,maxJump[i]表示在位置为i的石头青蛙的最大弹跳力(只有青蛙能跳到该石头上,maxJump[i]才大于0) [Mine]k是起跳石,i是目标石,计算从起跳石到目标石之间所有石头,可以跳到目标石时的弹跳力。计算后i++,如果目标石超过起跳石的最大弹跳力范围,k++ 这样k是可以直接跳到目标石的下限,不用每次都从头计算。 [Mine]maxJump数组并不是为了DP,它是为了减少Iterative 回溯。 [Mine]由于"either k - 1, k, or k + 1 units"限制,每次最大弹跳力不一定是最佳方案,所以需要记录每个位置可能得到的跳跃能力 [Mine]感觉递归+Meno更容易想到
[LeetCode#485] Max Consecutive Ones 最大连续1的个数 Given a binary array, find the maximum number of consecutive 1s in this array. Example 1: Input: [1,1,0,1,1,1] Output: 3 Explanation: The first two digits or the last three digits are consecutive 1s. The maximum number of consecutive 1s is 3. Note: The input array will only contain 0 and 1. The length of input array is a positive integer and will not exceed 10,000
#1 遍历一遍数组,用一个计数器cnt来统计1的个数,方法是如果当前数字为0,那么cnt重置为0,如果不是0,cnt自增1,然后每次更新结果res即可
[LeetCode#438] Find All Anagrams in a String 找出字符串中所有的变位词 Given a string s and a non-empty string p, find all the start indices of p's anagrams in s. Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100. The order of output does not matter. Example 1: Input: s: "cbaebabacd" p: "abc" Output: [0, 6] Explanation: The substring with start index = 0 is "cba", which is an anagram of "abc". The substring with start index = 6 is "bac", which is an anagram of "abc". Example 2: Input: s: "abab" p: "ab" Output: [0, 1, 2] Explanation: The substring with start index = 0 is "ab", which is an anagram of "ab". The substring with start index = 1 is "ba", which is an anagram of "ab". The substring with start index = 2 is "ab", which is an anagram of "ab".
#1 首先就要统计字符串p中字符出现的次数,然后从s的开头开始,每次找p字符串长度个字符,来验证字符个数是否相同,如果不相同出现了直接break,如果一直都相同了,则将起始位置加入结果res中 #2 用两个哈希表,分别记录p的字符个数,和s中前p字符串长度的字符个数,然后比较,如果两者相同,则将0加入结果res中,然后开始遍历s中剩余的字符,每次右边加入一个新的字符,然后去掉左边的一个旧的字符,每次再比较两个哈希表是否相同即可 #3 滑动窗口Sliding Window,与#2差不多,只是不每次对比hashmap,而是用一个变量记录和p的hashmap的差距。
[LeetCode#456] 132 Pattern 132模式 Given a sequence of n integers a1, a2, ..., an, a 132 pattern is a subsequence ai, aj, ak such that i < j < k and ai < ak < aj. Design an algorithm that takes a list of n numbers as input and checks whether there is a 132 pattern in the list. Note: n will be less than 15,000. Example 1: Input: [1, 2, 3, 4] Output: False Explanation: There is no 132 pattern in the sequence. Example 2: Input: [3, 1, 4, 2] Output: True Explanation: There is a 132 pattern in the sequence: [1, 4, 2]. Example 3: Input: [-1, 3, 2, 0] Output: True Explanation: There are three 132 patterns in the sequence: [-1, 3, 2], [-1, 3, 0] and [-1, 2, 0].
#1 首先我们来找第一个数,这个数需要最小,那么我们如果发现当前数字大于等于后面一个数字,我们就往下继续遍历,直到当前数字小于下一个数字停止。然后我们找第二个数字,这个数字需要最大,那么如果我们发现当前数字小于等于下一个数字就继续遍历,直到当前数字大于下一个数字停止。最后就找第三个数字,我们验证这个数字是否在之前两个数字的中间,如果没有找到,我们就从第二个数字的后面一个位置继续开始重新找这三个数字 [Mine]从左向右,找到first<second之后,找是否有third符合first<third<second,如果没有,就试试下一个first<second #2 类似#84 Largest Rectangle in Histogram (Hard)中栈的应用。 *从右向左*, 寻找 second>third,second和third越大越好,越大越容易找到first,为此记录第一对second>third之后,遇到比second更大的,就third=second, second=new, 然后一旦出现了first < third,就可以返回true
[LeetCode#411] Minimum Unique Word Abbreviation 最短的独一无二的单词缩写 A string such as "word" contains the following abbreviations: ["word", "1ord", "w1rd", "wo1d", "wor1", "2rd", "w2d", "wo2", "1o1d", "1or1", "w1r1", "1o2", "2r1", "3d", "w3", "4"] Given a target string and a set of strings in a dictionary, find an abbreviation of this target string with thesmallest possible length such that it does not conflict with abbreviations of the strings in the dictionary. Each number or letter in the abbreviation is considered length = 1. For example, the abbreviation "a32bc" has length = 4. Note: In the case of multiple answers as shown in the second example below, you may return any one of them. Assume length of target string = m, and dictionary size = n. You may assume that m ≤ 21, n ≤ 1000, and log2(n) + m ≤ 20. Examples: "apple", ["blade"] -> "a4" (because "5" or "4e" conflicts with "blade") "apple", ["plain", "amber", "blade"] -> "1p3" (other valid answers include "ap3", "a3e", "2p2", "3le", "3l1").
#1 首先找出target的所有的单词缩写的形式,然后按照长度来排序,小的排前面,我们用优先队列来自动排序,里面存一个pair,保存单词缩写及其长度,然后我们从最短的单词缩写开始,跟dictionary中所有的单词一一进行验证,看其是否是合法的单词的缩写,如果是,说明有冲突,直接break,进行下一个单词缩写的验证 #2 将单词缩写的冲突检测用位运算实现。 字典中的词和target,逐字母比对,相同为1,不同为0,生成二进制比对mask。 单词缩写abbr通过如下原则转化为二进制数字: 缩写中的字母替换为二进制1,数字覆盖的位数替换为二进制0 target缩写二进制和二进制比对mask相与, if NOT target_abbr & conflict_mask == target_abbr,这个缩写符合条件。 #2 Refer to http://bookshadow.com/weblog/2016/10/02/leetcode-minimum-unique-word-abbreviation/
[LeetCode#433] Minimum Genetic Mutation 最小基因变化 A gene string can be represented by an 8-character long string, with choices from "A", "C", "G", "T". Suppose we need to investigate about a mutation (mutation from "start" to "end"), where ONE mutation is defined as ONE single character changed in the gene string. For example, "AACCGGTT" -> "AACCGGTA" is 1 mutation. Also, there is a given gene "bank", which records all the valid gene mutations. A gene must be in the bank to make it a valid gene string. Now, given 3 things - start, end, bank, your task is to determine what is the minimum number of mutations needed to mutate from "start" to "end". If there is no such a mutation, return -1. Note: Starting point is assumed to be valid, so it might not be included in the bank. If multiple mutations are needed, all mutations during in the sequence must be valid. You may assume start and end string is not the same. Example 1: start: "AACCGGTT" end: "AACCGGTA" bank: ["AACCGGTA"] return: 1 Example 2: start: "AACCGGTT" end: "AAACGGTA" bank: ["AACCGGTA", "AACCGCTA", "AAACGGTA"] return: 2 Example 3: start: "AAAAACCC" end: "AACCCCCC" bank: ["AAAACCCC", "AAACCCCC", "AACCCCCC"] return: 3
BFS 计算距离场,或者每次转变一个字符,BFS 而是对于每个字符,我们都尝试将其换为一个新的字符,每次只换一个,这样会得到一个新的字符串,如果这个字符串在bank中存在,说明这样变换是合法的,加入visited集合和queue中等待下一次遍历,记得在下次置换字符的时候要将之前的还原。我们在queue中取字符串出来遍历的时候,先检测其是否和end相等,相等的话返回level,
[LeetCode#446] Arithmetic Slices II - Subsequence 算数切片之二 - 子序列 A sequence of numbers is called arithmetic if it consists of at least three elements and if the difference between any two consecutive elements is the same. For example, these are arithmetic sequences: 1, 3, 5, 7, 9 7, 7, 7, 7 3, -1, -5, -9 The following sequence is not arithmetic. 1, 1, 2, 5, 7 A zero-indexed array A consisting of N numbers is given. A subsequence slice of that array is any sequence of integers (P0, P1, ..., Pk) such that 0 ≤ P0 < P1 < ... < Pk < N. A subsequence slice (P0, P1, ..., Pk) of array A is called arithmetic if the sequence A[P0], A[P1], ..., A[Pk-1], A[Pk] is arithmetic. In particular, this means that k ≥ 2. The function should return the number of arithmetic subsequence slices in the array A. The input contains N integers. Every integer is in the range of -231 and 231-1 and 0 ≤ N ≤ 1000. The output is guaranteed to be less than 231-1. Example: Input: [2, 4, 6, 8, 10] Output: 7 Explanation: All arithmetic subsequence slices are: [2,4,6] [4,6,8] [6,8,10] [2,4,6,8] [4,6,8,10] [2,4,6,8,10] [2,6,10]
DP 一维数组dp,数组里的元素不是数字,而是放一个哈希表,建立等差数列的差值和其长度之间的映射。 2 4 6 8 10 2->1 4->1 6->1 8->1 2->2 4->1 6->1 2->3 4->2 2->4 [Mine]dp[i],以i与之前每个元素的差值为Key,value是用此差值已经组成的等差数列长度(可以是1)。计算所有i与之前元素j两两相差,如果j的dp有相同差值,那么就可以组成至少长度为3的等差数列 dp[i][diff]=dp[j][diff] + 1,其组合数为dp[j][diff]
[LeetCode#460] LFU Cache 最近最不常用页面置换缓存器 Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the following operations: get and put. get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. put(key, value) - Set or insert the value if the key is not already present. When the cache reaches its capacity, it should invalidate the least frequently used item before inserting a new item. For the purpose of this problem, when there is a tie (i.e., two or more keys that have the same frequency), the least recently used key would be evicted. Follow up: Could you do both operations in O(1) time complexity? Example: LFUCache cache = new LFUCache( 2 /* capacity */ ); cache.put(1, 1); cache.put(2, 2); cache.get(1); // returns 1 cache.put(3, 3); // evicts key 2 cache.get(2); // returns -1 (not found) cache.get(3); // returns 3. cache.put(4, 4); // evicts key 1. cache.get(1); // returns -1 (not found) cache.get(3); // returns 3 cache.get(4); // returns 4
LRU(Least Recnetly Used)算法是首先淘汰最长时间未被使用的页面, 而LFU(Least Frequently Used)是先淘汰一定时间内被访问次数最少的页面 hash#1 哈希表m来记录当前数据{key, value}和其出现次数之间的映射 hash#2 哈希表freq来建立频率和一个里面所有key都是当前频率的list之间的映射 hash#3 为了快速的定位freq中key的位置,我们再用一个哈希表iter来建立key和freq中key的位置之间的映射 [Mine]m是用来O(1)检测key是否在,更新和获取value的 freq是用来在O(1)找到记录的minfreq的所有key中删除一个 iter是用来在O(1)中增加访问次数时,更新freq用。 [Mine]注意list<int>::iterator>的使用,双向链表
[LeetCode#458] Poor Pigs 可怜的猪 There are 1000 buckets, one and only one of them contains poison, the rest are filled with water. They all look the same. If a pig drinks that poison it will die within 15 minutes. What is the minimum amount of pigs you need to figure out which bucket contains the poison within one hour. Answer this question, and write an algorithm for the follow-up general case. Follow-up: If there are n buckets and a pig drinking poison will die within m minutes, how many pigs (x) you need to figure out the "poison" bucket within p minutes? There is exact one bucket with poison.
[Mine]一头猪一次是一维两列 (判断两个桶) 两头猪一次是两维两列(判断四个桶) 三头猪一次是三维两列(判断八个桶) 一头猪两次是一维三列(判断三个桶) 两头猪两次是两维三列(判断九个桶) 三头猪两次是三维三列(判断二十七个桶) [Mine]理解一,用进制理解维度,进制位数=猪数,进制数=每一位能表示的数=次数+1=p/m + 1: 一次时,每个猪相当于二进制中的一位,所以桶数是2的指数倍(指数为猪的数量);两次时,每个猪相当于三进制的一位(每个猪通过两次可以准确表示0,1,2三个数),所以是3的指数倍。 每次每头猪同时喝的桶数是保持本位固定值,其他位的排列组合数量,即,每位可能取值^(位数-1)=(p/m+1)^(x-1) 理解二:多维扫描:维度=猪数,正多维体边长=次数+1=p/m + 1 一头猪时,每增加一次,能判断的桶数为p/m + 1 多头猪时,每个猪是正多维体的一个维度,正多维体边长是p/m + 1,通过多维交叉印证,正多维体中每一个点由每个维度上的一次实验结果表示 一次实验,一头猪要同时喝很多桶。每次每头猪同时喝的桶数是保持本维度坐标不变,在降维投影上覆盖的点数。比如三头猪,三维正立方体,x维度,第一次,就是[0, 0<=y<=p/m + 1, 0<=z<=p/m + 1]二维平面上的点。 这道题让我们求最少用多少猪来测,那么就是求数组的维度,我们知道了数组的总个数,所以要尽量增加数组的每维的长度,尽量减少维度。这里,数组的每维的长度其实都是测试的次数+1,所以我们首先要确定能测的次数,通过总测试时间除以毒发时间,再加上1就是测试次数。有了数组每维的长度(p/m+1),那么如果有x只猪,能测的桶数为(p/m+1)的x次方,现在我们给定了桶数N,要求x,就log一下就行 (p/m+1)^x=N, x=logN/log(p/m+1) [Mine] 如果a^x=N(a>0,且a≠1),则x叫做以a为底N的对数,记做x=log(a)(N),其中a要写于log右下。其中a叫做对数的底,N叫做真数。通常我们将以10为底的对数叫做常用对数,以e为底的对数称为自然对数。
[LeetCode#493] Reverse Pairs 翻转对 Given an array nums, we call (i, j) an important reverse pair if i < j and nums[i] > 2*nums[j]. You need to return the number of important reverse pairs in the given array. Example1: Input: [1,3,2,3,1] Output: 2 Example2: Input: [2,4,3,5,1] Output: 3 Note: The length of the given array will not exceed 50,000. All the numbers in the input array are in the range of 32-bit integer.
[Mine]最直接的方式就是对每个i,在其后无序数组用nums[i] /2分区,统计小于nums[i] /2的个数。所以是O(N^2)。 OR,逐一插入排序。 #1 顺序重现关系(Sequential Recurrence Relation),用式子表示是T(i, j) = T(i, j - 1) + C。这里的C就是处理最后一个数字的子问题,那么用文字来描述就是"已知翻转对的第二个数字为nums[j], 在子数组nums[i, j - 1]中找翻转对的第一个数字" 从后向前扫描,由于我们要在之前遍历过的数字中找符合条件的数字,怎么样利用BIT的特性来快速的找到是这种解法的最大难点。 树状数组Binary Indexed Tree(BIT) 要存的是该数字在有序数组中的位置,而且存入的也不是该数字本身,而是该数字出现的次数 [Mine]index是有序数组中小于等于此数字的数字个数和,即此数字在有序数组中其最后出现的位置。 [Mine]先将数组排成有序数组 在从后向前扫描,即遍历i找j的过程中,BIT的value是扫描过数字出现的次数。 用lower_bound在有序数组中确定符合nums[i] > 2*nums[j]的j最后出现的位置 这就是BIT的index,用BIT算出当前符合条件的<=j的数字出现次数总和。 sort: O(nlgn) + seek i: O(n) * (BIT update O(lgn) + BIT getSum O(lgn)) = O(nlogn) #2 分割重现关系(Partition Recurrence Relation),用式子表示是T(i, j) = T(i, m) + T(m+1, j) + C。这里的C就是处理合并两个部分的子问题,那么用文字来描述就是"已知翻转对的两个数字分别在子数组nums[i, m]和nums[m+1, j]之中,求满足要求的翻转对的个数" 如果两个子数组是有序的,那么我们可以用双指针的方法在线性时间内就可以统计出符合题意的翻转对的个数 在MergeSort的递归函数中,对于有序的两个子数组进行统计翻转对的个数,然后再逐层返回,这就完美的实现了上述的分割重现关系的思想。 MergeSort (Recursive) O(lgN) * Left/Right Pointer O(n) = O(nlgN) [Mine]T(i, j) = T(i, m) + T(m+1, j) + C,大区间解是小区间解之和,再加上跨区间解。在两个有序子数组中,只扫描一遍i in [i,m] and j in [m+1,j] 即可找到所有符合题意的跨区间解。 [Mine]从后向前遍历,维护一个有序数组,利用二分搜索来找符合题意的对数。这样查找时,确实是O(logN),但插入有序数组时就是O(N)了,这样整体就是O(N^2) #1 不做插入,利用BIT只做O(logN)的查找和O(logN)的getsum+update #2 不做整体遍历,整体O(NlogN)的mergeSort中,将两个有序子数组中找pair的过程平行放在了O(N)的merge中
[LeetCode#488] Zuma Game 祖玛游戏 Think about Zuma Game. You have a row of balls on the table, colored red(R), yellow(Y), blue(B), green(G), and white(W). You also have several balls in your hand. Each time, you may choose a ball in your hand, and insert it into the row (including the leftmost place and rightmost place). Then, if there is a group of 3 or more balls in the same color touching, remove these balls. Keep doing this until no more balls can be removed. Find the minimal balls you have to insert to remove all the balls on the table. If you cannot remove all the balls, output -1. Examples: Input: "WRRBBW", "RB" Output: -1 Explanation: WRRBBW -> WRR[R]BBW -> WBBW -> WBB[B]W -> WW Input: "WWRRBBWW", "WRBRW" Output: 2 Explanation: WWRRBBWW -> WWRR[R]BBWW -> WWBBWW -> WWBB[B]WW -> WWWW -> empty Input:"G", "GGGGG" Output: 2 Explanation: G -> G[G] -> GG[G] -> empty Input: "RBYYBBRRB", "YRBGB" Output: 3 Explanation: RBYYBBRRB -> RBYY[Y]BBRRB -> RBBBRRB -> RRRB -> B -> B[B] -> BB[B] -> empty Note: You may assume that the initial row of balls on the table won't have any 3 or more consecutive balls with the same color. The number of balls on the table won't exceed 20, and the string represents these balls is called "board" in the input. The number of balls in your hand won't exceed 5, and the string represents these balls is called "hand" in the input. Both input strings will be non-empty and only contain characters 'R','Y','B','G','W'.
board,不会有连续三个以上的同色球 #1 递归 看board上各个section的球。尝试用hand上的球去消除这个section,统计是否可行,所用球数 [Mine]对不同的board section用hand上的球解决 #2 递归 看hand上的各个球,尝试插入到board上相同颜色的section上,尝试各种同颜色section,看看是否可以把board消除干净。
[LeetCode#412] Fizz Buzz 嘶嘶嗡嗡 Write a program that outputs the string representation of numbers from 1 to n. But for multiples of three it should output "Fizz" instead of the number and for the multiples of five output "Buzz". For numbers which are multiples of both three and five output "FizzBuzz". Example: n = 15, Return: [ "1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz", "11", "Fizz", "13", "14", "FizzBuzz" ]
for (int i = 1; i <= n; ++i) { if (i % 15 == 0) res.push_back("FizzBuzz"); else if (i % 3 == 0) res.push_back("Fizz"); else if (i % 5 == 0) res.push_back("Buzz"); else res.push_back(to_string(i)); }
[LeetCode#449] Serialize and Deserialize BST 二叉搜索树的序列化和去序列化 Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment. Design an algorithm to serialize and deserialize a binary search tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary search tree can be serialized to a string and this string can be deserialized to the original tree structure. The encoded string should be as compact as possible. Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless.
same to #297 没发现跟之前那题有何不同,而且也没有看到能够利用BST性质的方法 #1 递归,先续遍历 #2 非递归,层序遍历 如果利用BST的性质的话, 是不需要特殊符号来表示空节点的 [Mine]先序存入;去序列化时,每取出一个数字,更新其左右支的取值范围,递归建造左右支。
[LeetCode#507] Perfect Number 完美数字 We define the Perfect Number is a positive integer that is equal to the sum of all its positive divisors except itself. Now, given an integer n, write a function that returns true when it is a perfect number and false when it is not. Example: Input: 28 Output: True Explanation: 28 = 1 + 2 + 4 + 7 + 14 Note: The input number n will not exceed 100,000,000. (1e8)
一个整数等于除其自身之外的所有的因子之和 #1 找其他因子的范围是[2, sqrt(n)]。我们遍历这之间所有的数字,如果可以被n整除,那么我们把i和num/i都加上,对于n如果是平方数的话,那么我们此时相同的因子加来两次,所以我们要减掉一次。还有就是在遍历的过程中如果累积和sum大于n了,直接返回false即可。在循环结束后,我们看sum是否和num相等 #2 在给定的n的范围内其实只有五个符合要求的完美数字 return num==6 || num==28 || num==496 || num==8128 || num==33550336;
[LeetCode#467] Unique Substrings in Wraparound String 封装字符串中的独特子字符串 Consider the string s to be the infinite wraparound string of "abcdefghijklmnopqrstuvwxyz", so s will look like this: "...zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd....". Now we have another string p. Your job is to find out how many unique non-empty substrings of p are present in s. In particular, your input is the string p and you need to output the number of different non-empty substrings of p in the string s. Note: p consists of only lowercase English letters and the size of p might be over 10000. Example 1: Input: "a" Output: 1 Explanation: Only the substring "a" of string "a" is in the string s. Example 2: Input: "cac" Output: 2 Explanation: There are two substrings "a", "c" of string "cac" in the string s. Example 3: Input: "zab" Output: 6 Explanation: There are six substrings "z", "a", "b", "za", "ab", "zab" of string "zab" in the string s.
一个无限长的封装字符串(26个字符按顺序无限循环组成的),然后又给了我们另一个字符串p,问我们p有多少非空子字符串在封装字符串中。题意的p的子字符串要么是单一的字符,要么是按字母顺序的子字符串。 [Mine]关键:字符串的子串中以原字符串最后一个字符为最后一个字符的子串数量等于字符串长度。 例如:abcd这个字符串,以d结尾的子字符串有abcd, bcd, cd, d,四个子串 坑1:z->a 对p中每个字符,如果它和之前是按照字母顺序的(包括z->a),且到此字母顺序子串长为len,那么以它结尾的子串数为len。 坑2: 同一个字母可能出现在不同的字母顺序子串中,这要取子串长大的 最后,累加26个字母在p中以此字母结尾的字母顺序子串长度。
[LeetCode#462] Minimum Moves to Equal Array Elements II 最少移动次数使数组元素相等之二 Given a non-empty integer array, find the minimum number of moves required to make all array elements equal, where a move is incrementing a selected element by 1 or decrementing a selected element by 1. You may assume the array's length is at most 10,000. Example: Input: [1,2,3] Output: 2 Explanation: Only two moves are needed (remember each move increments or decrements one element): [1,2,3] => [2,2,3] => [2,2,2]
一个长度为n的数组,每次对任意一个数字加1或者减1,让我们用最少的次数让数组所有值相等。 #1 O(nlgn) 首先给数组排序,那么我们最终需要变成的相等的数字就是中间的数,如果数组有奇数个,那么就是最中间的那个数字;如果是偶数个,那么就是中间两个数的区间中的任意一个数字。而两端的数字变成中间的一个数字需要的步数实际上就是两端数字的距离 #2 O(n) nth_element #3 O(nlgn) 改进版的暴力破解法: 它遍历了所有的数字,让每个数字都当作最后相等的值,然后算法出来总步数,每次和res比较 快速计算总步数: 排序, then, index i , value k (k = nums[i]) Total Steps to index i = 2 * i * k - n * k + sum - 2 * curSum [Mine]画个图,就好理解,排序好后是一个三角形。用i, k, sum, curSum就可以计算出平衡到index i的步数。
[LeetCode#415] Add Strings 字符串相加 Given two non-negative numbers num1 and num2 represented as string, return the sum of num1 and num2. Note: The length of both num1 and num2 is < 5100. Both num1 and num2 contains only digits 0-9. Both num1 and num2 does not contain any leading zero. You must not use any built-in BigInteger library or convert the inputs to integer directly.
一位一位相加,然后算和算进位,最后根据进位情况看需不需要补一个高位
[LeetCode#432] All O`one Data Structure 全O(1)的数据结构 Implement a data structure supporting the following operations: Inc(Key) - Inserts a new key with value 1. Or increments an existing key by 1. Key is guaranteed to be a non-empty string. Dec(Key) - If Key's value is 1, remove it from the data structure. Otherwise decrements an existing key by 1. If the key does not exist, this function does nothing. Key is guaranteed to be a non-empty string. GetMaxKey() - Returns one of the keys with maximal value. If no element exists, return an empty string "". GetMinKey() - Returns one of the keys with minimal value. If no element exists, return an empty string "". Challenge: Perform all these in O(1) time complexity.
为了让找到key在O(1)内,要hashmap 为了让GetMaxKey(),GetMinKey()在O(1),需要按照value大小排序,并在Inc(Key)和Dec(Key)以O(1)将相同value的key Set调整到排序好的位置(可能拆解或合并set)
[LeetCode#401] Binary Watch 二进制表 A binary watch has 4 LEDs on the top which represent the hours (0-11), and the 6 LEDs on the bottom represent the minutes (0-59). Each LED represents a zero or one, with the least significant bit on the right. For example, the above binary watch reads "3:25". Given a non-negative integer n which represents the number of LEDs that are currently on, return all possible times the watch could represent. Example: Input: n = 1 Return: ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", "0:16", "0:32"] Note: The order of output does not matter. The hour must not contain a leading zero, for example "01:00" is not valid, it should be "1:00". The minute must be consist of two digits and may contain a leading zero, for example "10:2" is not valid, it should be "10:02".
二进制手表,告诉我们有N个灯是亮的,问我们可能的时间。 #1利用到了bitset这个类,可以将任意进制数转为二进制,而且又用到了count函数,用来统计1的个数。那么时针从0遍历到11,分针从0遍历到59,然后我们把时针的数组左移6位加上分针的数值,然后统计1的个数,即为亮灯的个数,我们遍历所有的情况,当其等于num的时候,存入结果res中 #2 如果总共要取num个,我们在小时集合里取i个,算出和,然后在分钟集合里去num-i个求和,如果两个都符合题意,那么加入结果中即可。集合中取出几个的方法可以用递归计算Combinations #3 二进制表再叼也就72种情况,全给你列出来,然后采用跟上面那种解法相同的思路,时针集合取k个,分针集合取num-k个,然后存入结果中即可 [Mine]由于是有限个数组合。想怎么遍历都可以
[LeetCode#439] Ternary Expression Parser 三元表达式解析器 Given a string representing arbitrarily nested ternary expressions, calculate the result of the expression. You can always assume that the given expression is valid and only consists of digits 0-9, ?, :, T and F (T and Frepresent True and False respectively). Note: The length of the given string is ≤ 10000. Each number will contain only one digit. The conditional expressions group right-to-left (as usual in most languages). The condition will always be either T or F. That is, the condition will never be a digit. The result of the expression will always evaluate to either a digit 0-9, T or F. Example 1: Input: "T?2:3" Output: "2" Explanation: If true, then result is 2; otherwise result is 3. Example 2: Input: "F?1:T?4:5" Output: "4" Explanation: The conditional expressions group right-to-left. Using parenthesis, it is read/evaluated as: "(F ? 1 : (T ? 4 : 5))" "(F ? 1 : (T ? 4 : 5))" -> "(F ? 1 : 4)" or -> "(T ? 4 : 5)" -> "4" -> "4" Example 3: Input: "T?T?F:5:3" Output: "F" Explanation: The conditional expressions group right-to-left. Using parenthesis, it is read/evaluated as: "(T ? (T ? F : 5) : 3)" "(T ? (T ? F : 5) : 3)" -> "(T ? F : 3)" or -> "(T ? F : 5)" -> "F" -> "F"
从右边开始找到第一个问号,然后先处理这个三元表达式,然后再一步一步向左推,这也符合程序是从右向左执行的特点。 #1 stack #2 find_last_of
[LeetCode#417] Pacific Atlantic Water Flow 太平洋大西洋水流 Given an m x n matrix of non-negative integers representing the height of each unit cell in a continent, the "Pacific ocean" touches the left and top edges of the matrix and the "Atlantic ocean" touches the right and bottom edges. Water can only flow in four directions (up, down, left, or right) from a cell to another one with height equal or lower. Find the list of grid coordinates where water can flow to both the Pacific and Atlantic ocean. Note: The order of returned grid coordinates does not matter. Both m and n are less than 150. Example: Given the following 5x5 matrix: Pacific ~ ~ ~ ~ ~ ~ 1 2 2 3 (5) * ~ 3 2 3 (4) (4) * ~ 2 4 (5) 3 1 * ~ (6) (7) 1 4 5 * ~ (5) 1 1 2 4 * * * * * * Atlantic Return: [[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (positions with parentheses in above matrix).
从边缘当作起点开始遍历搜索,然后标记能到达的点位true,分别标记出pacific和atlantic能到达的点,那么最终能返回的点就是二者均为true的点 #1 DFS #2 BFS [Mine]DFS或BFS从海岸边找到制高点
[LeetCode#437] Path Sum III 二叉树的路径和之三 You are given a binary tree in which each node contains an integer value. Find the number of paths that sum to a given value. The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes). The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000. Example: root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8 10 / \ 5 -3 / \ \ 3 2 11 / \ \ 3 -2 1 Return 3. The paths that sum to 8 are: 1. 5 -> 3 2. 5 -> 2 -> 1 3. -3 -> 11
先序遍历二叉树 哈希表来建立所有的前缀路径之和跟其个数之间的映射,然后看子路径之和有没有等于给定值的 [Mine]I think #3 is wrong.
[LeetCode#491] Increasing Subsequences 递增子序列 Given an integer array, your task is to find all the different possible increasing subsequences of the given array, and the length of an increasing subsequence should be at least 2 . Example: Input: [4, 6, 7, 7] Output: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]] Note: The length of the given array will not exceed 15. The range of integer in the given array is [-100,100]. The given array may contain duplicates, and two equal integers should also be considered as a special case of increasing sequence.
先找出所有的子序列,从中找出递增的 检查 1. 序列长度大于等于2 2.递增 可以在记录结果时用set来去除重复项 也可以在递归过程中,用set来避免选用重复项 递归 迭代 [Mine]记录所有已知的大于0的升序序列,将新数字延长可能的升序序列,自己也是一个长度为1的升序序列。一旦长度大于等于3,记录在结果中。
[LeetCode#469] Convex Polygon 凸多边形 Given a list of points that form a polygon when joined sequentially, find if this polygon is convex (Convex polygon definition). Note: There are at least 3 and at most 10,000 points. Coordinates are in the range -10,000 to 10,000. You may assume the polygon formed by given points is always a simple polygon (Simple polygon definition). In other words, we ensure that exactly two edges intersect at each vertex, and that edges otherwise don't intersect each other. Example 1: [[0,0],[0,1],[1,1],[1,0]] Answer: True Explanation: Example 2: [[0,0],[0,10],[10,10],[10,0],[5,5]] Answer: False Explanation:
凸多边形的性质:所有的顶点角都不大于180度 利用以当前顶点为中心的矢量叉乘或者计算三角形的有符号面积判断多边形的方向以及当前顶点的凹凸性 假设当前连续的三个顶点分别是P1,P2,P3。计算向量P1P2,P2P3的叉乘,也可以计算三角形P1P2P3的面积,得到的结果如果大于0,则表示P3点在线段P1和P2的左侧,多边形的顶点是逆时针序列。然后依次计算下一个前后所组成向量的叉乘,如果在计算时,出现负值,则此多边形时凹多边形,如果所有顶点计算完毕,其结果都是大于0,则多边形时凸多边形。
[LeetCode#505] The Maze II 迷宫之二 There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolling up, down, left or right, but it won't stop rolling until hitting a wall. When the ball stops, it could choose the next direction. Given the ball's start position, the destination and the maze, find the shortest distance for the ball to stop at the destination. The distance is defined by the number of empty spaces traveled by the ball from the start position (excluded) to the destination (included). If the ball cannot stop at the destination, return -1. The maze is represented by a binary 2D array. 1 means the wall and 0 means the empty space. You may assume that the borders of the maze are all walls. The start and destination coordinates are represented by row and column indexes. Example 1 Input 1: a maze represented by a 2D array 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 1 0 0 0 0 0 Input 2: start coordinate (rowStart, colStart) = (0, 4) Input 3: destination coordinate (rowDest, colDest) = (4, 4) Output: 12 Explanation: One shortest way is : left -> down -> left -> down -> right -> down -> right. The total distance is 1 + 1 + 3 + 1 + 2 + 2 + 2 = 12. Example 2 Input 1: a maze represented by a 2D array 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 1 0 0 0 0 0 Input 2: start coordinate (rowStart, colStart) = (0, 4) Input 3: destination coordinate (rowDest, colDest) = (3, 2) Output: -1 Explanation: There is no way for the ball to stop at the destination. Note: There is only one ball and one destination in the maze. Both the ball and the destination exist on an empty space, and they will not be at the same position initially. The given maze does not contain border (like the red rectangle in the example pictures), but you could assume the border of the maze are all walls. The maze contains at least 2 empty spaces, and both the width and height of the maze won't exceed 100.
出到达终点,并停下来,的最少步数 dists[i][j]表示到达(i,j)这个位置时需要的最小步数,我们都初始化为整型最大值,在后在遍历的过程中不断用较小值来更新每个位置的步数值,最后我们来看终点位置的步数值,如果还是整型最大值的话,说明没法在终点处停下来,返回-1,否则就返回步数值。注意在压入栈的时候,我们对x和y进行了判断,只有当其不是终点的时候才压入栈,这样是做了优化,因为如果小球已经滚到终点了,我们就不要让它再滚了,就不把终点位置压入栈,免得它还滚 #1 BFS queue #2 DFS
[LeetCode#450] Delete Node in a BST 删除二叉搜索树中的节点 Given a root node reference of a BST and a key, delete the node with the given key in the BST. Return the root node reference (possibly updated) of the BST. Basically, the deletion can be divided into two stages: Search for a node to remove. If the node is found, delete the node. Note: Time complexity should be O(height of tree). Example: root = [5,3,6,2,4,null,7] key = 3 5 / \ 3 6 / \ \ 2 4 7 Given key to delete is 3. So we find the node with value 3 and delete it. One valid answer is [5,4,6,2,null,null,7], shown in the following BST. 5 / \ 4 6 / \ 2 7 Another valid answer is [5,2,6,null,4,null,7]. 5 / \ 2 6 \ \ 4 7
利用BST找到要删除的节点 首先判断是否有一个子节点不存在,那么我们就将root指向另一个节点,并返回给父节点(root就删除了) 难点就在于处理左右子节点都存在的情况,我们需要在右子树找到最小值,即右子树中最左下方的节点,然后将该最小值赋值给root,然后再在右子树中调用相同函数(递归)来在右子树(同样是BST)中删除这个值最小的节点
[LeetCode#471] Encode String with Shortest Length 最短长度编码字符串 Given a non-empty string, encode the string such that its encoded length is the shortest. The encoding rule is: k[encoded_string], where the encoded_string inside the square brackets is being repeated exactly k times. Note: k will be a positive integer and encoded string will not be empty or have extra space. You may assume that the input string contains only lowercase English letters. The string's length is at most 160. If an encoding process does not make the string shorter, then do not encode it. If there are several solutions, return any of them is fine. Example 1: Input: "aaa" Output: "aaa" Explanation: There is no way to encode it such that it is shorter than the input string, so we do not encode it. Example 2: Input: "aaaaa" Output: "5[a]" Explanation: "5[a]" is shorter than "aaaaa" by 1 character. Example 3: Input: "aaaaaaaaaa" Output: "10[a]" Explanation: "a9[a]" or "9[a]a" are also valid solutions, both of them have the same length = 5, which is the same as "10[a]". Example 4: Input: "aabcaabcd" Output: "2[aabc]d" Explanation: "aabc" occurs twice, so one answer can be "2[aabc]d". Example 5: Input: "abbbabbbcabbbabbbc" Output: "2[2[abbb]c]" Explanation: "abbbabbbc" occurs twice, but "abbbabbbc" can also be encoded to "2[abbb]c", so one answer can be "2[2[abbb]c]".
压缩字符串,把相同的字符串用中括号括起来,然后在前面加上出现的次数 二维的DP数组,其中dp[i][j]表示s在[i, j]范围内的字符串的缩写形式(如果缩写形式长度大于子字符串,那么还是保留子字符串,初始化为[i, j]范围内的字符串) 对于任意一段子字符串[i, j],我们我们以中间任意位置k来拆分成两段,比较dp[i][k]加上dp[k+1][j]的总长度和dp[i][j]的长度,将长度较小的字符串赋给dp[i][j] [Mine]知道各个子串的缩写形式,用不同分割方法,合并组成成更大子串的缩写形式。 关键是找sub = abcabc这种可压缩的情况,其中sub = s[i,j]。 巧妙方法:用sub+sub = abcabcabcabc,找第二个s在s+s里出现的位置,如果不是len(sub),则说明sub有重复,那么就要压缩这个sub,重复次数是len(sub) / indexOf(sub, 1)。 这里第二个s在s+s里出现的位置是3,不是len(sub)=6,说明重复次数是len(sub) / indexOf(sub, 1)=2 [Mine]无法判断准确的重复子串开始和结束时,只能遍历每个子串。 没有记录大子串中是否有小子串被重复子串压缩过,生成大子串压缩时,只能比较各种分割可能的小子串压缩长度和。
[LeetCode#416] Partition Equal Subset Sum 相同子集和分割 Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal. Note: Both the array size and each of the array element will not exceed 100. Example 1: Input: [1, 5, 11, 5] Output: true Explanation: The array can be partitioned as [1, 5, 5] and [11]. Example 2: Input: [1, 2, 3, 5] Output: false Explanation: The array cannot be partitioned into equal sum subsets.
原数组所有数字和一定是偶数,不然根本无法拆成两个和相同的子集合,那么我们只需要算出原数组的数字之和,然后除以2,就是我们的target #1 dp数组,其中dp[i]表示数字i是否是原数组的任意个子集合之和,那么我们我们最后只需要返回dp[target]就行了 对于遍历到的每个数字nums[i],我们需要更新我们的dp数组,要更新[nums[i], target]之间的值,那么对于这个区间中的任意一个数字j, dp[j] = dp[j] || dp[j - nums[i]] (nums[i] <= j <= target) [Mine]递归应该也可以找到一个集合,其sum为target #2 bisets的大小设为5001 因为题目中说了数组的长度和每个数字的大小都不会超过100,那么最大的和为10000,那么一半就是5000,前面再加上个0,就是5001了 遍历数字,对于遍历到的数字num,我们把bits向左平移num位,然后再或上原来的bits,这样所有的可能出现的和位置上都为1 最后去看bits[sum >> 1]是否为1即可 for (int num : nums) bits |= bits << num; return (sum % 2 == 0) && bits[sum >> 1]; [Mine]每个bit代表一种sum的可能,比如bit[5]代表sum可以等于5。那么bits |= bits << num,代表前面所有可能的sum与num相加,加上之前的sum的合集,即num加入后的所有可能sum。"前面所有可能的sum与num相加"在#2中就是左移,增加之前可能距离bit[0]的距离。 [Mine]一定不要想着了的bit是num的二进制,错。这里的bit[i]是可能的sum=i,一种距离bit[0]的距离
[LeetCode#465] Optimal Account Balancing 最优账户平衡 A group of friends went on holiday and sometimes lent each other money. For example, Alice paid for Bill's lunch for 10.ThenlaterChrisgaveAlice 5 for a taxi ride. We can model each transaction as a tuple (x, y, z) which means person x gave person y $z. Assuming Alice, Bill, and Chris are person 0, 1, and 2 respectively (0, 1, 2 are the person's ID), the transactions can be represented as [[0, 1, 10], [2, 0, 5]]. Given a list of transactions between a group of people, return the minimum number of transactions required to settle the debt. Note: A transaction will be given as a tuple (x, y, z). Note that x ≠ y and z > 0. Person's IDs may not be linear, e.g. we could have the persons 0, 1, 2 or we could also have the persons 0, 2, 6. Example 1: Input: [[0,1,10], [2,0,5]] Output: 2 Explanation: Person #0 gave person #1 $10. Person #2 gave person #0 $5. Two transactions are needed. One way to settle the debt is person #1 pays person #0 and #2 $5 each. Example 2: Input: [[0,1,10], [1,0,1], [1,2,5], [2,0,5]] Output: 1 Explanation: Person #0 gave person #1 $10. Person #1 gave person #0 $1. Person #1 gave person #2 $5. Person #2 gave person #0 $5. Therefore, person #1 only need to give person #0 $4, and all debt is settled.
哈希表来建立每个人和其账户的映射,其中账户若为正数,说明其他人欠你钱;如果账户为负数,说明你欠别人钱 递归: 遍历,递归选择正负两个账户,将index小的账户债务消减掉。如果本来正负不等额,会造成后面那个账户的正负变化。每次平一个帐号,知道所有账户都平了。记录步数最少方案
[LeetCode#453] Minimum Moves to Equal Array Elements 最少移动次数使数组元素相等 Given a non-empty integer array of size n, find the minimum number of moves required to make all array elements equal, where a move is incrementing n - 1 elements by 1. Example: Input: [1,2,3] Output: 3 Explanation: Only three moves are needed (remember each move increments two elements): [1,2,3] => [2,3,3] => [3,4,3] => [4,4,4]
我们每次可以对n-1个数字同时加1,问最少需要多少次这样的操作才能让数组中所有的数字相等。 需要换一个角度来看问题,其实给n-1个数字加1,效果等同于给那个未被选中的数字减1 #1 只要先找到最小值,然后累加每个数跟最小值之间的差值即可 #2 也可以求出数组的数字之和sum,然后用sum减去最小值和数组长度的乘积
[LeetCode#440] K-th Smallest in Lexicographical Order 字典顺序的第K小数字 Given integers n and k, find the lexicographically k-th smallest integer in the range from 1 to n. Note: 1 ≤ k ≤ n ≤ 109. Example: Input: n: 13 k: 2 Output: 10 Explanation: The lexicographical order is [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9], so the second smallest number is 10.
如果仔细观察字典顺序的数组,我们可以发现,其实这是个十叉树Denary Tree,就是每个节点的子节点可以有十个,但是由于n大小的限制,构成的并不是一个满十叉树。 难点就变成了如何计算出每个节点的子节点的个数,我们不停的用k减去子节点的个数,当k减到0的时候,当前位置的数字即为所求。 首先把1本身这一个数字加到step中,然后我们把范围扩大十倍,范围变成10到20之前,但是由于我们要考虑n的大小,由于n为13,所以只有4个子节点,这样我们就知道从数字1遍历到数字2需要经过5个数字,然后我们看step是否小于等于k,如果是,我们cur自增1,k减去step;如果不是,说明要求的数字在子节点中,我们此时cur乘以10,k自减1[Mine: 跳过了数字1],以此类推,直到k为0推出循环,此时cur即为所求 first = cur, last = cur + 1; while (first <= n) { step += min((long long)n + 1, last) - first; first *= 10; last *= 10; } [Mine]step等于cur下的十叉树的节点数。查找kth跨过了几棵树
[LeetCode#483] Smallest Good Base 最小的好基数 For an integer n, we call k>=2 a good base of n, if all digits of n base k are 1. Now given a string representing n, you should return the smallest good base of n in string format. Example 1: Input: "13" Output: "3" Explanation: 13 base 3 is 111. Example 2: Input: "4681" Output: "8" Explanation: 4681 base 8 is 11111. Example 3: Input: "1000000000000000000" Output: "999999999999999999" Explanation: 1000000000000000000 base 999999999999999999 is 11. Note: The range of n is [3, 10^18]. The string representing n is always valid and will not have leading zeros.
如果我们用k表示基数,m表示转为全1数字的位数,那么数字n就可以拆分为: n = 1 + k + k^2 + k^3 + ... + k^(m-1) m的下限为2,m最大,那么k就要最小,k最小是2,那么m最大只能为log(n + 1)/log2 since n > k^(m-1), k < n^(1 / (m-1)), k的下限为2 m从上限向下限扫描,用二分法找可能符合要求的k [Mine]感觉这种题都是用数学公式,计算出上下限,然后二分查找。
[LeetCode#474] Ones and Zeroes 一和零 In the computer world, use restricted resource you have to generate maximum benefit is what we always want to pursue. For now, suppose you are a dominator of m 0s and n 1s respectively. On the other hand, there is an array with strings consisting of only 0s and 1s. Now your task is to find the maximum number of strings that you can form with given m 0s and n 1s. Each 0 and 1 can be used at most once. Note: The given numbers of 0s and 1s will both not exceed 100 The size of given string array won't exceed 600. Example 1: Input: Array = {"10", "0001", "111001", "1", "0"}, m = 5, n = 3 Output: 4 Explanation: This are totally 4 strings can be formed by the using of 5 0s and 3 1s, which are "10,"0001","1","0" Example 2: Input: Array = {"10", "0", "1"}, m = 1, n = 1 Output: 2 Explanation: You could form "10", but then you'd have nothing left. Better form "0" and "1".
如果我们看到这种求总数,而不是列出所有情况的题,十有八九都是用DP来解 dp[i][j]表示有i个0和j个1时能组成的最多字符串的个数,而对于当前遍历到的字符串,我们统计出其中0和1的个数为zeros和ones dp[i][j] = max(dp[i][j], dp[i - zeros][j - ones] + 1); similar to #322 Coin Change
[LeetCode414] Third Maximum Number 第三大的数 Given a non-empty array of integers, return the third maximum number in this array. If it does not exist, return the maximum number. The time complexity must be in O(n). Example 1: Input: [3, 2, 1] Output: 1 Explanation: The third maximum is 1. Example 2: Input: [1, 2] Output: 2 Explanation: The third maximum does not exist, so the maximum (2) is returned instead. Example 3: Input: [2, 2, 3, 1] Output: 1 Explanation: Note that the third maximum here means the third maximum distinct number. Both numbers with value 2 are both considered as second maximum.
如果知道怎么求第二大的数,那么求第三大的数的思路都是一样的。那么我们用三个变量first, second, third来分别保存第一大,第二大,和第三大的数
[LeetCode#508] Most Frequent Subtree Sum 出现频率最高的子树和 Given the root of a tree, you are asked to find the most frequent subtree sum. The subtree sum of a node is defined as the sum of all the node values formed by the subtree rooted at that node (including the node itself). So what is the most frequent subtree sum value? If there is a tie, return all the values with the highest frequency in any order. Examples 1 Input: 5 / \ 2 -3 return [2, -3, 4], since all the values happen only once, return all of them in any order. Examples 2 Input: 5 / \ 2 -5 return [2], since 2 happens twice, however -5 only occur once. Note: You may assume the sum of values in any subtree is in the range of 32-bit signed integer.
子树是从下往上构建的,这种特点很适合使用后序遍历 cnt来记录当前最多的次数,hashmap记录sum和次数对
[LeetCode#408] Valid Word Abbreviation 验证单词缩写 Given a non-empty string s and an abbreviation abbr, return whether the string matches with the given abbreviation. A string such as "word" contains only the following valid abbreviations: ["word", "1ord", "w1rd", "wo1d", "wor1", "2rd", "w2d", "wo2", "1o1d", "1or1", "w1r1", "1o2", "2r1", "3d", "w3", "4"] Notice that only the above abbreviations are valid abbreviations of the string "word". Any other string is not a valid abbreviation of "word". Note: Assume s contains only lowercase letters and abbr contains only lowercase letters and digits. Example 1: Given s = "internationalization", abbr = "i12iz4n": Return true. Example 2: Given s = "apple", abbr = "a2e": Return false.
字母直接对比 数字,取完整有效数字,对比指针移动
[LeetCode#466] Count The Repetitions 计数重复个数 Define S = [s,n] as the string S which consists of n connected strings s. For example, ["abc", 3] ="abcabcabc". On the other hand, we define that string s1 can be obtained from string s2 if we can remove some characters from s2 such that it becomes s1. For example, "abc" can be obtained from "abdbec" based on our definition, but it can not be obtained from "acbbe". You are given two non-empty strings s1 and s2 (each at most 100 characters long) and two integers 0 ≤ n1 ≤ 106and 1 ≤ n2 ≤ 106. Now consider the strings S1 and S2, where S1=[s1,n1] and S2=[s2,n2]. Find the maximum integer M such that [S2,M] can be obtained from S1. Example: Input: s1="acb", n1=4 s2="ab", n2=2 Return: 2
寻找循环节。找到s2在S1中的循环节 我们遍历s1字符串n1次,表示每个s1字符串为一段,对于每段,我们有: 1. 出现在该段的s2字符串的累计出现次数[repeatCount] 2. 一个nextIndex,其中s2[nextIndex]表示在下一段s1中你所要寻找的第一个字符。(比如说s1="abc", s2="bac", 由于要寻找s2的第一个字符b,而b在s1中的位置是1,所以nextIndex=1;同理,比如s1="abca", s2="bac",那么nextIndex=2) [Mine]nextIndex记录每进入一段新s1时,要找的s2的nextIndex,一旦和之前某段s1的nextIndex相同,说明循环节开始,然后根据repeatCount,在此段及其之前所有s1找到的s2总数,计算出 repeatCnt[i]到第i个s1结束时,包含s2数目 interval:两个相同nextIndex的repeatCount之差 repeat :仅循环节(不包括第一个循环节前,和最后一个循环节后)在n1个s1中的循环节数量 patternCnt :repeatCnt[cur]-repeatCnt[start],times repeat remainCnt :假设刨去中间所有循环节,第一个循环节前加上最后一个循环节后,包含的s1数量repeatCnt[start + (n1 - start) % interval]; if 有循环节 return (patternCnt + remainCnt) / n2; else return repeatCnt[n1] / n2; [Mine]不好想到的 1.用nextIndex来确定循环节 2.remainCnt = repeatCnt[start + (n1 - start) % interval];
[LeetCode#514] Freedom Trail 自由之路 In the video game Fallout 4, the quest "Road to Freedom" requires players to reach a metal dial called the "Freedom Trail Ring", and use the dial to spell a specific keyword in order to open the door. Given a string ring, which represents the code engraved on the outer ring and another string key, which represents the keyword needs to be spelled. You need to find the minimum number of steps in order to spell all the characters in the keyword. Initially, the first character of the ring is aligned at 12:00 direction. You need to spell all the characters in the string key one by one by rotating the ring clockwise or anticlockwise to make each character of the string key aligned at 12:00 direction and then by pressing the center button. At the stage of rotating the ring to spell the key character key[i]: You can rotate the ring clockwise or anticlockwise one place, which counts as 1 step. The final purpose of the rotation is to align one of the string ring's characters at the 12:00 direction, where this character must equal to the character key[i]. If the character key[i] has been aligned at the 12:00 direction, you need to press the center button to spell, which also counts as 1 step. After the pressing, you could begin to spell the next character in the key (next stage), otherwise, you've finished all the spelling. Example: Input: ring = "godding", key = "gd" Output: 4 Explanation: For the first key character 'g', since it is already in place, we just need 1 step to spell this character. For the second key character 'd', we need to rotate the ring "godding" anticlockwise by two steps to make it become "ddinggo". Also, we need 1 more step for spelling. So the final output is 4. Note: Length of both ring and key will be in range 1 to 100. There are only lowercase letters in both strings and might be some duplcate characters in both strings. It's guaranteed that string key could always be spelled by rotating the string ring.
将密码字符串都转出来,让我们求最短的转动步数。 #1 DP dp[i][j]表示转动从i位置开始的key串所需要的最少步数(这里不包括spell的步数,因为spell可以在最后统一加上),此时表盘的12点位置是ring中的第j个字符。可以从key的末尾往前推,这样dp[0][0]就是我们所需要的结果 dp[i][j] = min(dp[i][j], step + dp[i + 1][k]); step是12点位置是ring中的第j个字符时,拨到一个key[i]位置所需要的step。k为拨到这个key[i]位置时 表盘的12点位置是ring中的第k个字符,且ring[k] == key[i] [Mine] dp[i][j] = min(dp[i][j], step + dp[i + 1][k]); ring[k] == key[i]; 意思是12位置是ring[j],目标是key[i]时到最终状态的最少步数为,12位置是ring[k] =key[i],即12点转到了key[i]之后 ,目标是key[i+1]时到最终状态的最少步数+12点位置ring[j]转到ring[k]的最少步数。 #DFS + memory memo[x][y],x为当前12点在ring中的offset,y为key中的目标字符。 需要一个hashmap(或v[26][])来记录每个字母在ring中的出现位置。对每个目标字符,ring上有多个位置,每个位置有正转,反转两个走法。 相同位置正转反转,肯定选step最短的。多个可选位置,就要DPS分别搜索。 [Mine]DFS + memory应该是最好想到的方法。 [Mine]DP是DFS+Memory的迭代写法:由于最后状态是确定的,我们要从最后向前推。把之前各种可能状态(遍历12点位置是ring上各个字符的状态)变到最终态的最佳解都计算出来。所以DP要显示出目标i,在key中的index,和,当前状态j,12点字符在ring中的index。 最后,挑选i=0, j=0的最佳解。 最初状态向后推,或最后状态向前推,都无法用贪婪算法。 [Mine]作者说这是顺序重现关系的例子,那么顺序重现关系可以理解为试图给出DFS+Memory的迭代写法的倒推过程:T(i, j) = T(i, j - 1) + C
[LeetCode#486] Predict the Winner 预测赢家 Given an array of scores that are non-negative integers. Player 1 picks one of the numbers from either end of the array followed by the player 2 and then player 1 and so on. Each time a player picks a number, that number will not be available for the next player. This continues until all the scores have been chosen. The player with the maximum score wins. Given an array of scores, predict whether player 1 is the winner. You can assume each player plays to maximize his score. Example 1: Input: [1, 5, 2] Output: False Explanation: Initially, player 1 can choose between 1 and 2. If he chooses 2 (or 1), then player 2 can choose from 1 (or 2) and 5. If player 2 chooses 5, then player 1 will be left with 1 (or 2). So, final score of player 1 is 1 + 2 = 3, and player 2 is 5. Hence, player 1 will never be the winner and you need to return False. Example 2: Input: [1, 5, 233, 7] Output: True Explanation: Player 1 first chooses 1. Then player 2 have to choose between 5 and 7. No matter which number player 2 choose, player 1 can choose 233. Finally, player 1 has more score (234) than player 2 (12), so you need to return True representing player1 can win. Note: 1 <= length of the array <= 20. Any scores in the given array are non-negative integers and will not exceed 10,000,000. If the scores of both players are equal, then player 1 is still the winner.
当前玩家赢返回true的条件就是递归调用下一个玩家输返回false #1 递归 如果数组有多个数字,我们分别生成两个新数组,一个是去掉首元素,一个是去掉尾元素,然后根据玩家标识分别调用不同的递归,只要下一个玩家两种情况中任意一种返回false了,那么当前玩家就可以赢了 #2 递归 Minimax的方法 + Memory dp[i][j]为遇到区间[i,j]数字的player能比对手多拿的score,所以ret=dp[0][n-1] > 0 int canWin(vector<int>& nums, int s, int e, vector<vector<int>>& dp) { if (dp[s][e] == -1) { dp[s][e] = (s == e) ? nums[s] : max(nums[s] - canWin(nums, s + 1, e, dp), nums[e] - canWin(nums, s, e - 1, dp)); } return dp[s][e]; } #3 DP dp[i][j] same meaning as #2 for (int i = 0; i < n; ++i) dp[i][i] = nums[i]; for (int len = 1; len < n; ++len) { for (int i = 0, j = len; j < n; ++i, ++j) { dp[i][j] = max(nums[i] - dp[i + 1][j], nums[j] - dp[i][j - 1]); } } return dp[0][n - 1] >= 0; [Mine]结果depend on中间任何区间的结果,大区间结果depend on小区间结果。 由小到大算出任意区间结果,就能拼出最终结果。
[LeetCode#457] Circular Array Loop 环形数组循环 You are given an array of positive and negative integers. If a number n at an index is positive, then move forward n steps. Conversely, if it's negative (-n), move backward n steps. Assume the first element of the array is forward next to the last element, and the last element is backward next to the first element. Determine if there is a loop in this array. A loop starts and ends at a particular index with more than 1 element along the loop. The loop must be "forward" or "backward'. Example 1: Given the array [2, -1, 1, 2, 2], there is a loop, from index 0 -> 2 -> 3 -> 0. Example 2: Given the array [-1, 2], there is no loop. Note: The given array is guaranteed to contain no element "0". Can you do it in O(n) time complexity and O(1) space complexity?
所谓的循环必须是一个方向的就是说不能跳到一个数,再反方向跳回来,这不算一个loop。比如[1, -1]就不是一个loop,而[1, 1]是一个正确的loop。 需要一个visited数组,来记录访问过的数字,然后我们遍历原数组,如果当前数字已经访问过了,直接跳过,否则就以当前位置坐标为起始点开始查找,进行while循环,将当前位置在visited数组中标记true,然后计算下一个位置,计算方法是当前位置坐标加上对应的数字 取余或补n,计算位置 如果next和cur相等,说明此时是一个数字的循环,不符合题意,再有就是检查二者的方向,数字是正数表示forward,若是负数表示backward,在一个loop中必须同正或同负,我们只要让二者相乘,如果结果是负数的话,说明方向不同,直接break掉。 [Mine]The loop must be "forward" or "backward'.所以必须"同正同负",这个不行: [2,2,-1,1] 0->2->1->3->0
[LeetCode#500] Keyboard Row 键盘行 Given a List of words, return the words that can be typed using letters of alphabet on only one row's of American keyboard like the image below. American keyboard Example 1: Input: ["Hello", "Alaska", "Dad", "Peace"] Output: ["Alaska", "Dad"] Note: You may use one character in the keyboard more than once. You may assume the input string will only contain letters of alphabet.
把键盘的三行字符分别保存到三个set中,然后遍历每个单词中的每个字符,分别看当前字符是否在三个集合中,如果在,对应的标识变量变为1,我们统计三个标识变量之和就知道有几个集合参与其中了
[LeetCode] 470. Implement Rand10() Using Rand7() 使用Rand7()来实现Rand10() Given a function rand7 which generates a uniform random integer in the range 1 to 7, write a function rand10 which generates a uniform random integer in the range 1 to 10. Do NOT use system's Math.random(). Example 1: Input: 1 Output: [7] Example 2: Input: 2 Output: [8,4] Example 3: Input: 3 Output: [8,1,10] Note: rand7 is predefined. Each testcase has one argument: n, the number of times that rand10 is called. Follow up: What is the expected value for the number of calls to rand7() function? Could you minimize the number of calls to rand7()?
拒绝采样 Rejection Sampling
[LeetCode#421] Maximum XOR of Two Numbers in an Array 数组中异或值最大的两个数字 Given a non-empty array of numbers, a0, a1, a2, ... , an-1, where 0 ≤ ai < 231. Find the maximum result of ai XOR aj, where 0 ≤ i, j < n. Could you do this in O(n) runtime? Example: Input: [3, 10, 5, 25, 2, 8] Output: 28 Explanation: The maximum result is 5 ^ 25 = 28.
按位遍历,按位猜并验证 若a^b=c,那么a=b^c,因为t是我们要验证的当前最大值,所以我们遍历set中的数时,和t异或后的结果仍在set中,说明两个前缀可以异或出t的值,所以我们更新res为t,继续遍历 [Mine]利用若a^b=c,那么a=b^c,从高位到低位猜结果:猜前缀为t,将array所有数的前缀放入set,如同前缀A=前缀B^t,就说明t=前缀A^前缀B,前缀t猜想正确。
[LeetCode#487] Max Consecutive Ones II 最大连续1的个数之二 Given a binary array, find the maximum number of consecutive 1s in this array if you can flip at most one 0. Example 1: Input: [1,0,1,1,0] Output: 4 Explanation: Flip the first zero will get the the maximum number of consecutive 1s. After flipping, the maximum number of consecutive 1s is 4. Note: The input array will only contain 0 and 1. The length of input array is a positive integer and will not exceed 10,000 Follow up: What if the input numbers come in one by one as an infinite stream? In other words, you can't store all numbers coming from the stream as it's too large to hold in memory. Could you solve it efficiently?
有一次将0翻转成1的机会 #1两个变量,记录间隔一个0的连续两组1的个数,找到更新结果 #2 如果题目中说能翻转k次怎么办呢 维护一个窗口[left,right]来容纳至少k个0。我们遇到了0,就累加zero的个数,然后判断如果此时0的个数大于k,那么我们我们右移左边界left,如果移除掉的nums[left]为0,那么我们zero自减1。如果不大于k,那么我们用窗口中数字的个数来更新res
[LeetCode#435] Non-overlapping Intervals 非重叠区间 Given a collection of intervals, find the minimum number of intervals you need to remove to make the rest of the intervals non-overlapping. Note: You may assume the interval's end point is always bigger than its start point. Intervals like [1,2] and [2,3] have borders "touching" but they don't overlap each other. Example 1: Input: [ [1,2], [2,3], [3,4], [1,3] ] Output: 1 Explanation: [1,3] can be removed and the rest of intervals are non-overlapping. Example 2: Input: [ [1,2], [1,2], [1,2] ] Output: 2 Explanation: You need to remove two [1,2] to make the rest of intervals non-overlapping. Example 3: Input: [ [1,2], [2,3] ] Output: 0 Explanation: You don't need to remove any of the intervals since they're already non-overlapping.
根据每个区间的start来做升序排序,然后我们开始要查找重叠区间,判断方法是看如果前一个区间的end大于后一个区间的start,那么一定是重复区间,此时我们结果res自增1,为了保证我们总体去掉的区间数最小,我们去掉那个end值较大的区间,而在代码中,我们并没有真正的删掉某一个区间,而是用一个变量last指向上一个需要比较的区间,我们将last指向end值较小的那个区间;如果两个区间没有重叠,那么此时last指向当前区间,继续进行下一次遍历 [Mine]找到一个overlap的就一定要删除一个区间,而且删除的一定end值大的。删掉之后,end大的区间消失,下次比较,用end小的区间
[LeetCode#492] Construct the Rectangle 构建矩形 For a web developer, it is very important to know how to design a web page's size. So, given a specific rectangular web page's area, your job by now is to design a rectangular web page, whose length L and width W satisfy the following requirements: 1. The area of the rectangular web page you designed must equal to the given target area. 2. The width W should not be larger than the length L, which means L >= W. 3. The difference between length L and width W should be as small as possible. You need to output the length L and the width W of the web page you designed in sequence. Example: Input: 4 Output: [2, 2] Explanation: The target area is 4, and all the possible ways to construct it are [1,4], [2,2], [4,1]. But according to requirement 2, [1,4] is illegal; according to requirement 3, [4,1] is not optimal compared to [2,2]. So the length L is 2, and the width W is 2. Note: The given area won't exceed 10,000,000 and is a positive integer The web page's width and length you designed must be positive integers.
根据面积来求出矩形的长和宽,要求长和宽的差距尽量的小,那么就是说越接近正方形越好 #1 先来判断一下是不是正方行,对面积开方,如果得到的不是整数,说明不是正方形。那么我们取最近的一个整数,看此时能不能整除,如果不行,就自减1,再看能否整除。最坏的情况就是面积是质数,最后减到了1,那么返回结果即可 #2 如果我们不想用开方运算sqrt的话,那就从1开始,看能不能整除,循环的终止条件是看平方值是否小于等于面积
[LeetCode#482] License Key Formatting 注册码格式化 Now you are given a string S, which represents a software license key which we would like to format. The string S is composed of alphanumerical characters and dashes. The dashes split the alphanumerical characters within the string into groups. (i.e. if there are M dashes, the string is split into M+1 groups). The dashes in the given string are possibly misplaced. We want each group of characters to be of length K (except for possibly the first group, which could be shorter, but still must contain at least one character). To satisfy this requirement, we will reinsert dashes. Additionally, all the lower case letters in the string must be converted to upper case. So, you are given a non-empty string S, representing a license key to format, and an integer K. And you need to return the license key formatted according to the description above. Example 1: Input: S = "2-4A0r7-4k", K = 4 Output: "24A0-R74K" Explanation: The string S has been split into two parts, each part has 4 characters. Example 2: Input: S = "2-4A0r7-4k", K = 3 Output: "24-A0R-74K" Explanation: The string S has been split into three parts, each part has 3 characters except the first part as it could be shorter as said above. Note: The length of string S will not exceed 12,000, and K is a positive integer. String S consists only of alphanumerical characters (a-z and/or A-Z and/or 0-9) and dashes(-). String S is non-empty.
正确的注册码的格式是每四个字符后面跟一个短杠,每一部分的长度为K,第一部分长度可以小于K,另外,字母必须是大写的 #1 从S的尾部往前遍历,把字符加入结果res,每K个后面加一个短杠,那么最后遍历完再把res翻转一下即可 [Mine]从后向前遍历,之后翻转
[LeetCode#477] Total Hamming Distance 全部汉明距离 The Hamming distance between two integers is the number of positions at which the corresponding bits are different. Now your job is to find the total Hamming distance between all pairs of the given numbers. Example: Input: 4, 14, 2 Output: 6 Explanation: In binary representation, the 4 is 0100, 14 is 1110, and 2 is 0010 (just showing the four bits relevant in this case). So the answer will be: HammingDistance(4, 14) + HammingDistance(4, 2) + HammingDistance(14, 2) = 2 + 2 + 2 = 6. Note: Elements of the given array are in the range of 0 to 10^9 Length of the array will not exceed 10^4.
此位能贡献的汉明距离是depend on 0跟1的个数,即每个1和每个0分别的距离累加,我们可以发现其实就是0的个数乘以1的个数。 比如4, 14, 2的倒数第二列,0,1,1,它贡献的汉明距离是2 将各个位上能贡献的汉明距离相加
[LeetCode#498] Diagonal Traverse 对角线遍历 Given a matrix of M x N elements (M rows, N columns), return all elements of the matrix in diagonal order as shown in the below image. Example: Input: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] Output: [1,2,4,7,5,3,6,8,9] Explanation: Note: The total number of elements of the given matrix will not exceed 10,000.
每移动一次,横纵坐标都要变化,向右上移动的话要坐标加上[-1, 1],向左下移动的话要坐标加上[1, -1] 向右上和左下两个对角线方向遍历的时候都会有越界的可能,但是除了左下角和右上角的位置越界需要改变两个坐标之外,其余的越界只需要改变一个。 vector<vector<int>> dirs{{-1,1}, {1,-1}}; for (int i = 0; i < m * n; ++i) { res[i] = matrix[r][c]; r += dirs[k][0]; c += dirs[k][1]; if (r >= m) {r = m - 1; c += 2; k = 1 - k;} if (c >= n) {c = n - 1; r += 2; k = 1 - k;} if (r < 0) {r = 0; k = 1 - k;} if (c < 0) {c = 0; k = 1 - k;} } Note: change direction k = 1 - k; #2 根据横纵左边之和的奇偶性来判断遍历的方向,然后对于越界情况再单独处理即可 #3 确定每一行的坐标范围,其中下边界low = max(0, i - n + 1),这样可以保证下边界不会小于0,而上边界high = min(i, m - 1),这样也保证了上边界不会大于m-1,如果是偶数层,则从上边界往下边界遍历,反之如果是奇数层,则从下边界往上边界遍历 [Mine]#3找到扫描斜边的r和c的取值范围 int m = matrix.size(), n = matrix[0].size() for (int i = 0; i < m + n - 1; ++i) { int low = max(0, i - n + 1), high = min(i, m - 1); 这里low和high是r的取值范围,i是r和c之和。所以目标就是matrix[r][i - c]
[LeetCode#424] Longest Repeating Character Replacement 最长重复字符置换 Given a string that consists of only uppercase English letters, you can replace any letter in the string with another letter at most k times. Find the length of a longest substring containing all repeating letters you can get after performing the above operations. Note: Both the string's length and k will not exceed 104. Example 1: Input: s = "ABAB", k = 2 Output: 4 Explanation: Replace the two 'A's with two 'B's or vice versa. Example 2: Input: s = "AABABBA", k = 1 Output: 4 Explanation: Replace the one 'A' in the middle with 'B' and form "AABBBBA". The substring "BBBB" has the longest repeating letters, which is 4.
滑动窗口 如果没有k的限制,让我们求把字符串变成只有一个字符重复的字符串需要的最小置换次数,那么就是字符串的总长度减去出现次数最多的字符的个数。如果加上k的限制,我们其实就是求满足(子字符串的长度减去出现次数最多的字符个数)<=k的最大子字符串长度即可 [Mine]窗口找到第一个满足条件的substring后,继续向前滑动时,即使条件不满足了,也不用缩小。保持窗口大小,向前滑动。因为你不需要找到所有符合条件的substring,你要找的是最大的那个。 新char破坏条件时,就向前滑动窗口,直到窗口内的substring重新符合要求,看新char是否能扩大窗口,窗口大小保持之前套到的最大那个。
[LeetCode#506] Relative Ranks 相对排名 Given scores of N athletes, find their relative ranks and the people with the top three highest scores, who will be awarded medals: "Gold Medal", "Silver Medal" and "Bronze Medal". Example 1: Input: [5, 4, 3, 2, 1] Output: ["Gold Medal", "Silver Medal", "Bronze Medal", "4", "5"] Explanation: The first three athletes got the top three highest scores, so they got "Gold Medal", "Silver Medal" and "Bronze Medal". For the left two athletes, you just need to output their relative ranks according to their scores. Note: N is a positive integer and won't exceed 10,000. All the scores of athletes are guaranteed to be unique.
用score排序,记录坐标。 #1 堆排序 priority_queue #2 快排 sort
[LeetCode#484] Find Permutation 找全排列 By now, you are given a secret signature consisting of character 'D' and 'I'. 'D' represents a decreasing relationship between two numbers, 'I' represents an increasing relationship between two numbers. And our secret signature was constructed by a special integer array, which contains uniquely all the different number from 1 to n (n is the length of the secret signature plus 1). For example, the secret signature "DI" can be constructed by array [2,1,3] or [3,1,2], but won't be constructed by array [3,2,4] or [2,1,3,4], which are both illegal constructing special string that can't represent the "DI" secret signature. On the other hand, now your job is to find the lexicographically smallest permutation of [1, 2, ... n] could refer to the given secret signature in the input. Example 1: Input: "I" Output: [1,2] Explanation: [1,2] is the only legal initial spectial string can construct secret signature "I", where the number 1 and 2 construct an increasing relationship. Example 2: Input: "DI" Output: [2,1,3] Explanation: Both [2,1,3] and [3,1,2] can construct the secret signature "DI", but since we want to find the one with the smallest lexicographical permutation, you need to output [2,1,3] Note: The input string will only contain the character 'D' and 'I'. The length of input string is a positive integer and will not exceed 10,000
由D和I两个字符组成的字符串,分别表示对应位置的升序和降序,要我们根据这个字符串生成对应的数字字符串。 #1 只有D对应的位置附近的数字才需要变换,而且变换方法就是倒置一下字符串,我们要做的就是通过D的位置来确定需要倒置的子字符串的起始位置和长度即可。通过观察,我们需要记录D的起始位置i,还有D的连续个数k,那么我们只需要在数组中倒置[i, i+k]之间的数字即可 #2 对于D先跳过,找到下一个I或结尾,倒序填入之间的数字, [Mine] 对于I间的D,全部倒序转入。 对于每一个I,就是倒序填入only一个数字。连续的I其实还是升序。
[LeetCode#402] Remove K Digits 去掉K位数字 Given a non-negative integer num represented as a string, remove k digits from the number so that the new number is the smallest possible. Note: The length of num is less than 10002 and will be ≥ k. The given num does not contain any leading zero. Example 1: Input: num = "1432219", k = 3 Output: "1219" Explanation: Remove the three digits 4, 3, and 2 to form the new number 1219 which is the smallest. Example 2: Input: num = "10200", k = 1 Output: "200" Explanation: Remove the leading 1 and the number is 200. Note that the output must not contain leading zeroes. Example 3: Input: num = "10", k = 2 Output: "0" Explanation: Remove all the digits from the number and it is left with nothing which is 0.
由于数字的相对顺序不变,和#321 Create Maximum Number思路一样 去掉的数字遵从高位优先,除非是相邻的两个数字。相邻数字去掉大的。 for (char c : num) { while (k && res.size() && res.back() > c) { res.pop_back(); --k; } res.push_back(c); } res is the char kept.
[LeetCode#423] Reconstruct Original Digits from English 从英文中重建数字 Given a non-empty string containing an out-of-order English representation of digits 0-9, output the digits in ascending order. Note: Input contains only lowercase English letters. Input is guaranteed to be valid and can be transformed to its original digits. That means invalid inputs such as "abc" or "zerone" are not permitted. Input length is less than 50,000. Example 1: Input: "owoztneoer" Output: "012" Example 2: Input: "fviefuro" Output: "45"
由于题目中限定了输入的字符串一定是有效的,那么不会出现无法成功重建的情况,这里需要用个trick。 1. 现有些的单词的字符是独一无二的,比如z,只出现在zero中,还有w,u,x,g这四个单词,分别只出现在two,four,six,eight中,那么这五个数字的个数就可以被确定了, 2. 由于含有o的单词有zero,two,four,one,其中前三个都被确定了,那么one的个数也就知道了; 3. 由于含有h的单词有eight,three,其中eight个数已知,那么three的个数就知道了; 4. 由于含有f的单词有four,five,其中four个数已知,那么five的个数就知道了; 5. 由于含有s的单词有six,seven,其中six个数已知,那么seven的个数就知道了; 6. 由于含有i的单词有six,eight,five,nine,其中前三个都被确定了,那么nine的个数就知道了 按这个顺序"zero", "two", "four", "six", "eight", "one", "three", "five", "seven", "nine"就能找出所有的个数了
[LeetCode#475] Heaters 加热器 Winter is coming! Your first job during the contest is to design a standard heater with fixed warm radius to warm all the houses. Now, you are given positions of houses and heaters on a horizontal line, find out minimum radius of heaters so that all houses could be covered by those heaters. So, your input will be the positions of houses and heaters seperately, and your expected output will be the minimum radius standard of heaters. Note: Numbers of houses and heaters you are given are non-negative and will not exceed 25000. Positions of houses and heaters you are given are non-negative and will not exceed 10^9. As long as a house is in the heaters' warm radius range, it can be warmed. All the heaters follow your radius standard and the warm radius will the same. Example 1: Input: [1,2,3],[2] Output: 1 Explanation: The only heater was placed in the position 2, and if we use the radius 1 standard, then all the houses can be warmed. Example 2: Input: [1,2,3,4],[1,4] Output: 1 Explanation: The two heater was placed in the position 1 and 4. We need to use radius 1 standard, then all the houses can be warmed.
目标是houses中的每一个数字都要被cover到 排序 #1 在heater中两个数一组进行检查,如果下面一个heater和当前house位置差的绝对值小于等于当前heater和当前house位置差的绝对值,即下一个heater可以以更短距离cover这个house,继续遍历下一个heater,如果不行,就说明找到了这个house的最短cover heater,更新res,遍历下一个house #2 二分查找法来快速找到第一个大于等于当前house位置的数,如果这个数存在,那么我们可以算出其和house的差值,并且如果这个数不是heater的首数字,我们可以算出house和前面一个数的差值,这两个数中取较小的为cover当前house的最小半径,然后我们每次更新结果res即可 [Mine]house的cover heater一定是在它邻近的一个或两个heater中距离最近的一个。
[LeetCode#448] Find All Numbers Disappeared in an Array 找出数组中所有消失的数字 Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once. Find all the elements of [1, n] inclusive that do not appear in this array. Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space. Example: Input: [4,3,2,7,8,2,3,1] Output: [5,6]
类似#442, 核心是就是找nums[i]和nums[nums[i] - 1]的关系 #1 对于每个数字nums[i],如果其对应的nums[nums[i] - 1]是正数,我们就赋值为其相反数,如果已经是负数了,就不变了,那么最后我们只要把留下的正数对应的位置加入结果res中即可 #2 将nums[i]置换到其对应的位置nums[nums[i]-1]上去。 最后在对应位置检验,如果nums[i]和i+1不等,那么我们将i+1存入结果res中即可 #3 在nums[nums[i]-1]位置累加数组长度n,注意nums[i]-1有可能越界,所以我们需要对n取余
[LeetCode#472] Concatenated Words 连接的单词 Given a list of words (without duplicates), please write a program that returns all concatenated words in the given list of words. A concatenated word is defined as a string that is comprised entirely of at least two shorter words in the given array. Example: Input: ["cat","cats","catsdogcats","dog","dogcatsdog","hippopotamuses","rat","ratcatdogcat"] Output: ["catsdogcats","dogcatsdog","ratcatdogcat"] Explanation: "catsdogcats" can be concatenated by "cats", "dog" and "cats"; "dogcatsdog" can be concatenated by "dog", "cats" and "dog"; "ratcatdogcat" can be concatenated by "rat", "cat", "dog" and "cat". Note: The number of elements of the given array will not exceed 10,000 The length sum of elements in the given array will not exceed 600,000. All the input string will only include lower case letters. The returned elements order does not matter.
给了一个由单词组成的数组,某些单词是可能由其他的单词组成的,让我们找出所有这样的单词。 similar to #139 Word Break DP[i]表示在这个word中,到0~i子串是否完全由dict拼接出。 对每一个word的每个子串,从短子串到长子串,计算其是否在dict中有。 DP[i]=DP[j] && dict.count(word.substr(j, i - j)) 0<=j<i
[LeetCode#409] Longest Palindrome 最长回文串 Given a string which consists of lowercase or uppercase letters, find the length of the longest palindromes that can be built with those letters. This is case sensitive, for example "Aa" is not considered a palindrome here. Note: Assume the length of given string will not exceed 1,010. Example: Input: "abccccdd" Output: 7 Explanation: One longest palindrome that can be built is "dccaccd", whose length is 7.
给了我们一个字符串,让我们找出可以组成的最长的回文串的长度,由于字符顺序打乱 #1 所有偶数个字符的出现总和,然后如果有奇数个字符的话,我们取取出其最大偶数,然后最后结果加1即可 #2 字符串长度减去max of 0和奇数字符数量-1。 s.size() - max(0, odds - 1); [Mine]所有奇数数量的字符,每个组字符要浪费一个字符,最多只有一组奇数数量字符可以不浪费地用在回文串中。
[LeetCode#499] The Maze III 迷宫之三 There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolling up (u), down (d), left (l) or right (r), but it won't stop rolling until hitting a wall. When the ball stops, it could choose the next direction. There is also a hole in this maze. The ball will drop into the hole if it rolls on to the hole. Given the ball position, the hole position and the maze, find out how the ball could drop into the hole by moving the shortest distance. The distance is defined by the number of empty spaces traveled by the ball from the start position (excluded) to the hole (included). Output the moving directions by using 'u', 'd', 'l' and 'r'. Since there could be several different shortest ways, you should output the lexicographically smallest way. If the ball cannot reach the hole, output "impossible". The maze is represented by a binary 2D array. 1 means the wall and 0 means the empty space. You may assume that the borders of the maze are all walls. The ball and the hole coordinates are represented by row and column indexes. Example 1 Input 1: a maze represented by a 2D array 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 Input 2: ball coordinate (rowBall, colBall) = (4, 3) Input 3: hole coordinate (rowHole, colHole) = (0, 1) Output: "lul" Explanation: There are two shortest ways for the ball to drop into the hole. The first way is left -> up -> left, represented by "lul". The second way is up -> left, represented by 'ul'. Both ways have shortest distance 6, but the first way is lexicographically smaller because 'l' < 'u'. So the output is "lul". Example 2 Input 1: a maze represented by a 2D array 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 Input 2: ball coordinate (rowBall, colBall) = (4, 3) Input 3: hole coordinate (rowHole, colHole) = (3, 0) Output: "impossible" Explanation: The ball cannot reach the hole. Note: There is only one ball and one hole in the maze. Both the ball and hole exist on an empty space, and they will not be at the same position initially. The given maze does not contain border (like the red rectangle in the example pictures), but you could assume the border of the maze are all walls. The maze contains at least 2 empty spaces, and the width and the height of the maze won't exceed 30.
让球在最小步数内滚到陷阱之中,此时返回的并不是最小步数,而是滚动的方向,用u, r, d, l 这四个字母来分别表示上右下左,而且在步数相等的情况下,让我们返回按字母排序小的答案。 # Queue 迭代 dists[i][j]表示到达(i,j)这个位置时需要的最小步数,我们都初始化为整型最大值,在后在遍历的过程中不断用较小值来更新每个位置的步数值。我们还需要用一个哈希表来建立每个位置跟滚到该位置的方向字符串之间的映射,这里我们用一个trick,将二维坐标转(i,j)为一个数字i*n+j,这实际上就是把二维数组拉成一维数组的操作 [Mine]记录路径上每个拐点的最短步数和最符合题意path,用queue记录备选方向。拐点不是已知最短,就不入Queue #2 DFS
[LeetCode#459] Repeated Substring Pattern 重复子字符串模式 Given a non-empty string check if it can be constructed by taking a substring of it and appending multiple copies of the substring together. You may assume the given string consists of lowercase English letters only and its length will not exceed 10000. Example 1: Input: "abab" Output: True Explanation: It's the substring "ab" twice. Example 2: Input: "aba" Output: False Example 3: Input: "abcabcabcabc" Output: True Explanation: It's the substring "abc" four times. (And the substring "abcabc" twice.)
给了我们一个字符串,问其是否能拆成n个重复的子串 #1 从原字符串长度的一半遍历到1,如果当前长度能被总长度整除(二分,三分,四分。。。),说明可以分成若干个子字符串,我们将这些子字符串拼接起来看跟原字符串是否相等 #2 一位数组dp[i]表示,到位置i-1为止的重复字符串的字符个数,不包括被重复的那个字符串 如果是"abcabcabc",那么dp数组为[0 0 0 0 1 2 3 4 5 6] while (i < n) { if (str[i] == str[j]) dp[++i] = ++j; else if (j == 0) ++i; else j = dp[j]; } return dp[n] && (dp[n] % (n - dp[n]) == 0); [Mine]感觉就是求KMP算法中的next数组时的当前位置的最大相同前缀后缀的长度 [Mine]最后一个字符有相同前后缀,并且最长前后缀能够整除剩余部分,即前后缀一定大于等于剩余部分,另外根据前后缀属性,剩余部分很可能就是能填满整个字符串的最短重复子字符串。
[LeetCode#455] Assign Cookies 分点心 Assume you are an awesome parent and want to give your children some cookies. But, you should give each child at most one cookie. Each child i has a greed factor gi, which is the minimum size of a cookie that the child will be content with; and each cookie j has a size sj. If sj >= gi, we can assign the cookie j to the child i, and the child i will be content. Your goal is to maximize the number of your content children and output the maximum number. Note: You may assume the greed factor is always positive. You cannot assign more than one cookie to one child. Example 1: Input: [1,2,3], [1,1] Output: 1 Explanation: You have 3 children and 2 cookies. The greed factors of 3 children are 1, 2, 3. And even though you have 2 cookies, since their size is both 1, you could only make the child whose greed factor is 1 content. You need to output 1. Example 2: Input: [1,2], [1,2,3] Output: 2 Explanation: You have 2 children and 3 cookies. The greed factors of 2 children are 1, 2. You have 3 cookies and their sizes are big enough to gratify all of the children, You need to output 2.
给了我们一堆cookie,每个cookie的大小不同,还有一堆小朋友,每个小朋友的胃口也不同的,问我们当前的cookie最多能满足几个小朋友。 对两个数组进行排序,让小的在前面。然后我们先拿最小的cookie给胃口最小的小朋友,看能否满足,能的话,我们结果res自加1,然后再拿下一个cookie去满足下一位小朋友;如果当前cookie不能满足当前小朋友,那么我们就用下一块稍大一点的cookie去尝试满足当前的小朋友。当cookie发完了或者小朋友没有了我们停止遍历
[LeetCode#464] Can I Win 我能赢吗 In the "100 game," two players take turns adding, to a running total, any integer from 1..10. The player who first causes the running total to reach or exceed 100 wins. What if we change the game so that players cannot re-use integers? For example, two players might take turns drawing from a common pool of numbers of 1..15 without replacement until they reach a total >= 100. Given an integer maxChoosableInteger and another integer desiredTotal, determine if the first player to move can force a win, assuming both players play optimally. You can always assume that maxChoosableInteger will not be larger than 20 and desiredTotal will not be larger than 300. Example Input: maxChoosableInteger = 10 desiredTotal = 11 Output: false Explanation: No matter which integer the first player choose, the first player will lose. The first player can choose an integer from 1 up to 10. If the first player choose 1, the second player can only choose integers from 2 up to 10. The second player will win by choosing 10 and get a total = 11, which is >= desiredTotal. Same with other integers chosen by the first player, the second player will always win.
给了我们一堆数字,然后两个人,每人每次选一个数字,看数字总数谁先到给定值 递归+Memo 如果给定的数字范围大于等于目标值的话,直接返回true。 如果给定的数字总和小于目标值的话,说明谁也没法赢,返回false。 使用一个整型数按位来记录数组中的某个数字是否使用,so bits int used record当前可选数字的状态,以它为key,hashmap记录当前状态已知的结果 bool canWin(int length, int total, int used, unordered_map<int, bool>& m) { if (m.count(used)) return m[used]; for (int i = 0; i < length; ++i) { int cur = (1 << i); if ((cur & used) == 0) { if (total <= i + 1 || !canWin(length, total - (i + 1), cur | used, m)) { m[used] = true; return true; } } } m[used] = false; return false; } [Mine]先手能赢,即自己能赢 或 对手会输
[LeetCode#479] Largest Palindrome Product 最大回文串乘积 Find the largest palindrome made from the product of two n-digit numbers. Since the result could be very large, you should return the largest palindrome mod 1337. Example: Input: 2 Output: 987 Explanation: 99 x 91 = 9009, 9009 % 1337 = 987 Note: The range of n is [1,8].
给我们一个数字n,问两个n位数的乘积组成的最大回文数是多少,返回的结果对1337取余。 当n>1时,两个n位数乘积的最大回文数一定是2n位的 确定出n位数的范围,最大值upper (10^n-1),可以取到,最小值lower(upper / 10),不能取到。然后我们遍历这区间的所有数字,对于每个遍历到的数字,我们用当前数字当作回文数的前半段,将其翻转一下拼接到后面,此时组成一个回文数。来验证这个回文数能否由两个n位数相乘的来。 验证方法:从upper开始遍历,结束位置是当前数的平方大于回文数,因为我们遍历的是相乘得到回文数的两个数中的较大数,一旦超过这个范围,就变成较小数了,就重复计算了。 [Mine]从可能的结果入手,进行验证。 从upper到lower,拼回文数,验证。 验证: for (long j = upper; j * j > 回文数; --j) { if (回文数 % j == 0)
[LeetCode#451] Sort Characters By Frequency 根据字符出现频率排序 Given a string, sort it in decreasing order based on the frequency of characters. Example 1: Input: "tree" Output: "eert" Explanation: 'e' appears twice while 'r' and 't' both appear once. So 'e' must appear before both 'r' and 't'. Therefore "eetr" is also a valid answer. Example 2: Input: "cccaaa" Output: "cccaaa" Explanation: Both 'c' and 'a' appear three times, so "aaaccc" is also a valid answer. Note that "cacaca" is incorrect, as the same characters must be together. Example 3: Input: "Aabb" Output: "bbAa" Explanation: "bbaA" is also a valid answer, but "Aabb" is incorrect. Note that 'A' and 'a' are treated as two different characters.
肯定要先统计出每个字符出现的个数 #1 利用优先队列的自动排序的特点,把个数和字符组成pair放到优先队列里排好序后,再取出来组成结果res即可 #2 使用STL自带的sort来做 #3 因为某个字符的出现次数不可能超过s的长度,所以我们将每个字符根据其出现次数放入数组中的对应位置,那么最后我们只要从后往前遍历数组所有位置,将不为空的位置的字符串加入结果res中即可 [Mine]一定要记住#3的基数排序方法
[LeetCode#425] Word Squares 单词平方 Given a set of words (without duplicates), find all word squares you can build from them. A sequence of words forms a valid word square if the kth row and column read the exact same string, where 0 ≤ k < max(numRows, numColumns). For example, the word sequence ["ball","area","lead","lady"] forms a word square because each word reads the same both horizontally and vertically. b a l l a r e a l e a d l a d y Note: There are at least 1 and at most 1000 words. All words will have the exact same length. Word length is at least 1 and at most 5. Each word contains only lowercase English alphabet a-z. Example 1: Input: ["area","lead","wall","lady","ball"] Output: [ [ "wall", "area", "lead", "lady" ], [ "ball", "area", "lead", "lady" ] ] Explanation: The output consists of two word squares. The order of output does not matter (just the order of words in each word square matters). Example 2: Input: ["abat","baba","atan","atal"] Output: [ [ "baba", "abat", "baba", "atan" ], [ "baba", "abat", "baba", "atal" ] ] Explanation: The output consists of two word squares. The order of output does not matter (just the order of words in each word square matters).
能快速的通过前缀来判断某个单词是否存在,这是解题的关键 #1 利用哈希表来建立前缀和所有包含此前缀单词的集合之前的映射 #2 建立前缀树Trie,在node里面加上以它为prefix所有可能的word,List<String> 第一个单词:""为前缀,在words数组里随便取一个word1,确定长度 第二个单词:在剩下的words里取出一个以word1[1]为前缀的word2 第三个单词:在剩下的里取出一个以word1[2]+word2[2]为前缀的word3 第四个单词:在剩下的里取出一个以word1[3]+word2[3]+word3[3]为前缀的word4 第五个单词:在剩下的里取出一个以word1[4]+word2[4]+word3[4]+word4[4]为前缀的word5 [Mine] 以四乘四Square看,左上右下对角线字母无需Mirror,其他都是沿对角线Mirror。所以竖排扫描与横排前缀相同。DFS来递归穷举出符合条件的squares
[LeetCode#463] Island Perimeter 岛屿周长 You are given a map in form of a two-dimensional integer grid where 1 represents land and 0 represents water. Grid cells are connected horizontally/vertically (not diagonally). The grid is completely surrounded by water, and there is exactly one island (i.e., one or more connected land cells). The island doesn't have "lakes" (water inside that isn't connected to the water around the island). One cell is a square with side length 1. The grid is rectangular, width and height don't exceed 100. Determine the perimeter of the island. Example: [[0,1,0,0], [1,1,1,0], [0,1,0,0], [1,1,0,0]] Answer: 16 Explanation: The perimeter is the 16 yellow stripes in the image below:
若干连在一起的格子形成了一个小岛,规定了图中只有一个相连的岛,且岛中没有湖,让我们求岛的周长 #1 我们对于每个格子的四条边分别来处理,首先看左边的边,只有当左边的边处于第一个位置或者当前格子的左面没有岛格子的时候,左边的边计入周长。其他三条边的分析情况都跟左边的边相似 #2 对于每个岛屿格子先默认加上四条边,然后检查其左面和上面是否有岛屿格子,有的话分别减去两条边,这样也能得到正确的结果
[LeetCode#447] Number of Boomerangs 回旋镖的数量 Given n points in the plane that are all pairwise distinct, a "boomerang" is a tuple of points (i, j, k) such that the distance between i and j equals the distance between i and k (the order of the tuple matters). Find the number of boomerangs. You may assume that n will be at most 500 and coordinates of points are all in the range [-10000, 10000] (inclusive). Example: Input: [[0,0],[1,0],[2,0]] Output: 2 Explanation: The two boomerangs are [[1,0],[0,0],[2,0]] and [[1,0],[2,0],[0,0]]
要求第一个点和第二个点之间的距离跟第一个点和第三个点之间的距离相等. 如果有n个点和a距离相等,那么排列方式为n(n-1),这属于最简单的排列组合问题了 遍历所有点,让每个点都做一次点a,然后遍历其他所有点,统计和a距离相等的点有多少个,然后分别带入n(n-1)计算结果并累加到res中,只有当n大于等于2时,res值才会真正增加 int a = points[i].first - points[j].first; int b = points[i].second - points[j].second; ++m[a * a + b * b]; for (auto it = m.begin(); it != m.end(); ++it) { res += it->second * (it->second - 1); } [Mine]虽然这里实际是c*c,但我们实际需要知道距离相同的点个数,所以无所谓。
[LeetCode#434] Number of Segments in a String 字符串中的分段数量 Count the number of segments in a string, where a segment is defined to be a contiguous sequence of non-space characters. Please note that the string does not contain any non-printable characters. Example: Input: "Hello, my name is John" Output: 5
计算空格
[LeetCode#436] Find Right Interval 找右区间 Given a set of intervals, for each of the interval i, check if there exists an interval j whose start point is bigger than or equal to the end point of the interval i, which can be called that j is on the "right" of i. For any interval i, you need to store the minimum interval j's index, which means that the interval j has the minimum start point to build the "right" relationship for interval i. If the interval j doesn't exist, store -1 for the interval i. Finally, you need output the stored value of each interval as an array. Note: You may assume the interval's end point is always bigger than its start point. You may assume none of these intervals have the same start point. Example 1: Input: [ [1,2] ] Output: [-1] Explanation: There is only one interval in the collection, so it outputs -1. Example 2: Input: [ [3,4], [2,3], [1,2] ] Output: [-1, 0, 1] Explanation: There is no satisfied "right" interval for [3,4]. For [2,3], the interval [3,4] has minimum-"right" start point; For [1,2], the interval [2,3] has minimum-"right" start point. Example 3: Input: [ [1,4], [2,3], [3,4] ] Output: [-1, 2, -1] Explanation: There is no satisfied "right" interval for [1,4] and [3,4]. For [2,3], the interval [3,4] has minimum-"right" start point.
让我们找每个区间的最近右区间,要保证右区间的start要大于等于当前区间的end start值降序排列。然后我们遍历区间集合,对于每个区间,我们在数组中找第一个小于当前区间的end值的位置,如果数组中第一个数就小于当前区间的end,那么说明该区间不存在右区间,结果res中加入-1;如果找到了第一个小于当前区间end的位置,那么往前推一个就是第一个大于等于当前区间end的start
[LeetCode#452] Minimum Number of Arrows to Burst Balloons 最少数量的箭引爆气球 There are a number of spherical balloons spread in two-dimensional space. For each balloon, provided input is the start and end coordinates of the horizontal diameter. Since it's horizontal, y-coordinates don't matter and hence the x-coordinates of start and end of the diameter suffice. Start is always smaller than end. There will be at most 104 balloons. An arrow can be shot up exactly vertically from different points along the x-axis. A balloon with xstart and xend bursts by an arrow shot at x if xstart ≤ x ≤ xend. There is no limit to the number of arrows that can be shot. An arrow once shot keeps travelling up infinitely. The problem is to find the minimum number of arrows that must be shot to burst all balloons. Example: Input: [[10,16], [2,8], [1,6], [7,12]] Output: 2 Explanation: One way is to shoot one arrow for example at x = 6 (bursting the balloons [2,8] and [1,6]) and another arrow at x = 11 (bursting the other two balloons).
贪婪算法来做的题,因为局部最优解就等于全局最优解 [Mine]排序,在第一区间射一箭,找到能爆的最大end,然后在未爆的第一区间,再射一箭。 [Mine]箭没有一定要射在重叠区域,只要能连锁爆炸就行
[LeetCode#495] Teemo Attacking 提莫攻击 In LLP world, there is a hero called Teemo and his attacking can make his enemy Ashe be in poisoned condition. Now, given the Teemo's attacking ascending time series towards Ashe and the poisoning time duration per Teemo's attacking, you need to output the total time that Ashe is in poisoned condition. You may assume that Teemo attacks at the very beginning of a specific time point, and makes Ashe be in poisoned condition immediately. Example 1: Input: [1,4], 2 Output: 4 Explanation: At time point 1, Teemo starts attacking Ashe and makes Ashe be poisoned immediately. This poisoned status will last 2 seconds until the end of time point 2. And at time point 4, Teemo attacks Ashe again, and causes Ashe to be in poisoned status for another 2 seconds. So you finally need to output 4. Example 2: Input: [1,2], 2 Output: 3 Explanation: At time point 1, Teemo starts attacking Ashe and makes Ashe be poisoned. This poisoned status will last 2 seconds until the end of time point 2. However, at the beginning of time point 2, Teemo attacks Ashe again who is already in poisoned status. Since the poisoned status won't add up together, though the second poisoning attack will still work at time point 2, it will stop at the end of time point 3. So you finally need to output 3. Note: You may assume the length of given time series array won't exceed 10000. You may assume the numbers in the Teemo's attacking time series and his poisoning time duration per attacking are non-negative integers, which won't exceed 10,000,000.
贪心算法,比较相邻两个时间点的时间差,如果小于duration,就加上这个差,如果大于或等于,就加上duration即可
[LeetCode#490] The Maze 迷宫 There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolling up, down, left or right, but it won't stop rolling until hitting a wall. When the ball stops, it could choose the next direction. Given the ball's start position, the destination and the maze, determine whether the ball could stop at the destination. The maze is represented by a binary 2D array. 1 means the wall and 0 means the empty space. You may assume that the borders of the maze are all walls. The start and destination coordinates are represented by row and column indexes. Example 1 Input 1: a maze represented by a 2D array 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 1 0 0 0 0 0 Input 2: start coordinate (rowStart, colStart) = (0, 4) Input 3: destination coordinate (rowDest, colDest) = (4, 4) Output: true Explanation: One possible way is : left -> down -> left -> down -> right -> down -> right. Example 2 Input 1: a maze represented by a 2D array 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 1 0 0 0 0 0 Input 2: start coordinate (rowStart, colStart) = (0, 4) Input 3: destination coordinate (rowDest, colDest) = (3, 2) Output: false Explanation: There is no way for the ball to stop at the destination. Note: There is only one ball and one destination in the maze. Both the ball and the destination exist on an empty space, and they will not be at the same position initially. The given maze does not contain border (like the red rectangle in the example pictures), but you could assume the border of the maze are all walls. The maze contains at least 2 empty spaces, and both the width and height of the maze won't exceed 100.
这次迷宫是有一个滚动的小球,这样就不是每次只走一步了,而是朝某一个方向一直滚,直到遇到墙或者边缘才停下来,问小球是否可以停在目的地 [Mine]目的地必定至少有一边是墙,球砸向墙壁,停下来 #1 DFS+memory #1 BFS+queue
[LeetCode#442] Find All Duplicates in an Array 找出数组中所有重复项 Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once. Find all the elements that appear twice in this array. Could you do it without extra space and in O(n) runtime? Example: Input: [4,3,2,7,8,2,3,1] Output: [2,3]
这类问题的核心是就是找nums[i]和nums[nums[i] - 1]的关系 #1 对于每个nums[i],我们将其对应的nums[nums[i] - 1]取相反数,如果其已经是负数了,说明之前存在过,我们将其加入结果res中即可 #2 将nums[i]置换到其对应的位置nums[nums[i]-1]上去.我们最后在对应位置检验,如果nums[i]和i+1不等,那么我们将nums[i]存入结果res中即可 #3 在nums[nums[i]-1]位置累加数组长度n,最后要找出现两次的数只需要看nums[i]的值是否大于2n即可 [Mine]想尽办法在nums[nums[i] - 1]上做标记(负数啦,index和value不match啦,+n越界啦)
[LeetCode#473] Matchsticks to Square 火柴棍组成正方形 Remember the story of Little Match Girl? By now, you know exactly what matchsticks the little match girl has, please find out a way you can make one square by using up all those matchsticks. You should not break any stick, but you can link them up, and each matchstick must be used exactly one time. Your input will be several matchsticks the girl has, represented with their stick length. Your output will either be true or false, to represent whether you could make one square using all the matchsticks the little match girl has. Example 1: Input: [1,1,2,2,2] Output: true Explanation: You can form a square with length 2, one side of the square came two sticks with length 1. Example 2: Input: [3,3,3,3,4] Output: false Explanation: You cannot find a way to form a square with all the matchsticks. Note: The length sum of the given matchsticks is in the range of 0 to 10^9. The length of the given matchstick array will not exceed 15.
这道题实际上是让我们将一个数组分成四个和相等的子数组 #1 优化过的递归来解 DFS+ 数组从大到小的顺序排序,这样大的数字先加,如果超过target了,就直接跳过了后面的再次调用递归的操作 [Mine]把数字放在各个边试试,和已有边上的相加,超过target的,跳过;找不到任何可以放入的方案,忽略;找到恰好填满四边的方案,成功。 num[0]放在sum[0]上试试,DPS..... num[0]放在sum[1]上试试,DPS..... 四叉树 #2 迭代 一个变量all,初始化为(1 << n) - 1,这是什么意思呢,all其实是一个mask,数组中有多少个数字,all就有多少个1 两个一维数组masks和validHalf,其中masks保存和target相等的几个数字位置的mask,validHalf保存某个mask是否是总和的一半 [Mine]用all来计算各种数组组合的sum,如果等于target,它就是一个备选的边,存入masks。 如果找到两个无共同数字的mask,那么half = mask1 | mask2 就可以组成双边方案,存在validHalf,如果validHalf[all ^ half]也恰巧是true,说明剩余的数字也可以组成一个双边方案,这就是四边方案 思路和#416 Partition Equal Subset Sum不一样,#416是平分两份,这里是平分四份。#416只要找到一次target就行,这里需要找到至少三次互无交集的target组合 所以要么DPS+sort,穷举各种组合。 要么利用bitmap记录可以组成target的备选方案,利用bitmap操作找到互无交集的四个方案。
[LeetCode#502] IPO 上市 Suppose LeetCode will start its IPO soon. In order to sell a good price of its shares to Venture Capital, LeetCode would like to work on some projects to increase its capital before the IPO. Since it has limited resources, it can only finish at most k distinct projects before the IPO. Help LeetCode design the best way to maximize its total capital after finishing at most k distinct projects. You are given several projects. For each project i, it has a pure profit Pi and a minimum capital of Ci is needed to start the corresponding project. Initially, you have W capital. When you finish a project, you will obtain its pure profit and the profit will be added to your total capital. To sum up, pick a list of at most k distinct projects from given projects to maximize your final capital, and output your final maximized capital. Example 1: Input: k=2, W=0, Profits=[1,2,3], Capital=[0,1,1]. Output: 4 Explanation: Since your initial capital is 0, you can only start the project indexed 0. After finishing it you will obtain profit 1 and your capital becomes 1. With capital 1, you can either start the project indexed 1 or the project indexed 2. Since you can choose at most 2 projects, you need to finish the project indexed 2 to get the maximum capital. Therefore, output the final maximized capital, which is 0 + 1 + 3 = 4. Note: You may assume all numbers in the input are non-negative integers. The length of Profits array and Capital array will not exceed 50,000. The answer is guaranteed to fit in a 32-bit signed integer.
这道题说初始时我们的资本为0,可以交易k次,并且给了我们提供了交易所需的资本和所能获得的利润,让我们求怎样选择k次交易,使我们最终的资本最大。 #1 用贪婪算法来解,每一次都选择资本范围内最大利润的进行交易,那么我们首先应该建立资本和利润对,然后根据资本的大小进行排序,然后我们根据自己当前的资本,用二分搜索法在有序数组中找第一个大于当前资本的交易的位置,然后往前退一步就是最后一个不大于当前资本的交易,然后向前遍历,找到利润最大的那个的进行交易,把利润加入资本W中,然后将这个交易对删除,这样我们就可以保证在进行k次交易后,我们的总资本最大 #2 贪婪算法 资本利润对放在最小堆中,取出小于当前资本的,然后利润资本存入最大堆中
[LeetCode#404] Sum of Left Leaves 左子叶之和 Find the sum of all left leaves in a given binary tree. Example: 3 / \ 9 20 / \ 15 7 There are two left leaves in the binary tree, with values 9 and 15 respectively. Return 24.
遍历 当前结点是否是左子节点,如果是左子节点,而且该左子节点再没有子节点了说明其是左子叶,那么我们将其值加入结果res中
[LeetCode#422] Valid Word Square 验证单词平方 Given a sequence of words, check whether it forms a valid word square. A sequence of words forms a valid word square if the kth row and column read the exact same string, where 0 ≤k < max(numRows, numColumns). Note: The number of words given is at least 1 and does not exceed 500. Word length will be at least 1 and does not exceed 500. Each word contains only lowercase English alphabet a-z. Example 1: Input: [ "abcd", "bnrt", "crmy", "dtye" ] Output: true Explanation: The first row and first column both read "abcd". The second row and second column both read "bnrt". The third row and third column both read "crmy". The fourth row and fourth column both read "dtye". Therefore, it is a valid word square. Example 2: Input: [ "abcd", "bnrt", "crm", "dt" ] Output: true Explanation: The first row and first column both read "abcd". The second row and second column both read "bnrt". The third row and third column both read "crm". The fourth row and fourth column both read "dt". Therefore, it is a valid word square. Example 3: Input: [ "ball", "area", "read", "lady" ] Output: false Explanation: The third row reads "read" while the third column reads "lead". Therefore, it is NOT a valid word square.
遍历二维数组,然后验证对应位上的字符是否相等的问题
[LeetCode#407] Trapping Rain Water II 收集雨水之二 Given an m x n matrix of positive integers representing the height of each unit cell in a 2D elevation map, compute the volume of water it is able to trap after raining. Note: Both m and n are less than 110. The height of each unit cell is greater than 0 and is less than 20,000. Example: Given the following 3x6 height map: [ [1,4,3,1,3,2], [3,2,1,3,2,4], [2,3,3,2,3,1] ] Return 4.
采用模拟海平面上升的方法来做,我们维护一个海平面高度mx,初始化为最小值,从1开始往上升,那么我们BFS遍历的时候就需要从高度最小的格子开始遍历,那么我们的queue就不能使用普通队列了,而是使用优先级队列,将高度小的放在队首,最先取出(小堆),抬高水面,在not visited块中找洼地。 [Mine]不断涨水,Visited标记表明这块上不可能有水。所以初始化边上的块都是visited。随着水涨,从visited 小堆中向内BSF,高于水面的只入堆,标visited。低于水面的,水可灌入,由于一定是从最短边BSF发现的,所以可以达到的水面高度一定是mx-hight[i][j]。 [Mine]技术:最小堆,BFS;先把桶壁圈出,从小堆中取值,作为水面,淹没一个块,BFS这个块,如果发现比水面高的,就是新的桶壁,入堆,发现比水面低的,保持水面不动,用BSF寻找洼地旁的洼地,并计算蓄水量。此水面能灌入的洼地都计算后(visited),再冲小堆中取下一个可以掩埋的块。 这是将模具浸入水中的过程,不是下雨的过程。
[LeetCode#444] Sequence Reconstruction 序列重建 Check whether the original sequence org can be uniquely reconstructed from the sequences in seqs. The org sequence is a permutation of the integers from 1 to n, with 1 ≤ n ≤ 104. Reconstruction means building a shortest common supersequence of the sequences in seqs (i.e., a shortest sequence so that all sequences in seqs are subsequences of it). Determine whether there is only one sequence that can be reconstructed from seqs and it is the org sequence. Example 1: Input: org: [1,2,3], seqs: [[1,2],[1,3]] Output: false Explanation: [1,2,3] is not the only one sequence that can be reconstructed, because [1,3,2] is also a valid sequence that can be reconstructed. Example 2: Input: org: [1,2,3], seqs: [[1,2]] Output: false Explanation: The reconstructed sequence can only be [1,2]. Example 3: Input: org: [1,2,3], seqs: [[1,2],[1,3],[2,3]] Output: true Explanation: The sequences [1,2], [1,3], and [2,3] can uniquely reconstruct the original sequence [1,2,3]. Example 4: Input: org: [4,1,5,2,6,3], seqs: [[5,2,6,3],[4,1,5,2]] Output: true
问这些子序列能否唯一的重建出原序列。能唯一重建的意思就是任意两个数字的顺序必须是一致的 #1 用了一个一维数组pos来记录org中每个数字对应的位置 int n = org.size() for (int i = 0; i < n; ++i) pos[org[i]] = i; 对每一个seq[i - 1], seq[i],检查其是否match org中的顺序。如果seq[i - 1]和 seq[i]在org也是相邻关系,说明字符seq[i]在org中已经被确认了。 #2 用两个哈希表, 其中m为数字和其位置之间的映射,pre为当前数字和其前一个位置的数字在org中的位置之间的映射, 当遍历到某一个数字的时候,我们看当前数字是否在pre中有映射,如果没有的话,我们建立该映射,注意如果是第一个位置的数字的话,其前面数字设为-1。如果该映射存在的话,我们对比前一位数字在org中的位置和当前的映射值的大小,取其中较大值。最后我们遍历一遍org,看每个数字的映射值是否是前一个数字的位置,如果有不是的返回false,全部验证成功返回true [Mine]org中每一个字符及其前面的字符的顺序都是在seqs中有明确指示的。 每个org的字符都可以在seq中找到其确定的前字符。 Att: 如果seq[i - 1]和 seq[i]在org也是相邻关系,说明字符seq[i]在org中已经被确认了。
[LeetCode#406] Queue Reconstruction by Height 根据高度重建队列 Suppose you have a random list of people standing in a queue. Each person is described by a pair of integers(h, k), where h is the height of the person and k is the number of people in front of this person who have a height greater than or equal to h. Write an algorithm to reconstruct the queue. Note: The number of people is less than 1,100. Example Input: [[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]] Output: [[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]
队列中的每个元素是一个pair,分别为身高和前面身高不低于当前身高的人的个数,让我们重新排列队列,使得每个pair的第二个参数都满足题意 #1 首先我们给队列先排个序,按照身高高的排前面,如果身高相同,则第二个数小的排前面。然后我们新建一个空的数组,遍历之前排好序的数组,然后根据每个元素的第二个数字,将其插入到res数组中对应的位置 [Mine]每个pair第二个数是比它高或一样高的人的相对位置。身高倒序插入,使这样的相对位置是直接确定的。 [Mine]身高倒序保证,已经排好的人一定比要加入的人高(或相等),用插入点来保证pair.second。后加入的人无论插入到哪里都不破坏已有pair的正确性 #2 如#1排序好后,通过一个变量cnt和k的关系来将元素向前移动到正确位置,移动到方法是通过每次跟前面的元素交换位置 [Mine]相当于身高倒序后,再用pair.second,做冒泡排序调整。
[LeetCode#420] Strong Password Checker 密码强度检查器 A password is considered strong if below conditions are all met: It has at least 6 characters and at most 20 characters. It must contain at least one lowercase letter, at least one uppercase letter, and at least one digit. It must NOT contain three repeating characters in a row ("...aaa..." is weak, but "...aa...a..." is strong, assuming other conditions are met). Write a function strongPasswordChecker(s), that takes a string s as input, and return the MINIMUM change required to make s a strong password. If s is already strong, return 0. Insertion, deletion or replace of any one character are all considered as one change.
非强密码串主要有的三个问题: 1. 长度问题 2. 缺失字符或数字 3. 重复字符 我们的目标就是尽可能的找出这种能解决多种问题的操作。由于情况三(重复字符)可以用三种操作来解决,所以我们分别来看能同时解决情况一和情况三,跟同时解决情况二和情况三的操作。 1. 当密码串长度小于6时,情况一和情况二的操作步骤可以完全覆盖情况三 2. 当密码串长度大于等于6个的时候,我们尽量不要用插入字符操作,因为这有可能会使长度超过限制。 3. 在解决情况三的时候还要综合考虑到情况一(超长时)。对于重复字符个数k大于等于3的情况,我们并不是直接将其删除到2个,而是先将其删除到最近的(3m+2)个,那么如果k正好被3整除,那么我们直接变为k-1,如果k除以3余1,那么变为k-2。这样做的好处是3m+2个重复字符可以最高效的用替换m个字符来去除重复。 [Mine]分支较多,综合考虑各种情况