Easy题目总结

Posted xero10

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Easy题目总结相关的知识,希望对你有一定的参考价值。

正常技巧题

 

implement queue using stack: https://leetcode.com/problems/implement-queue-using-stacks/

用两个stack,push时存入stack1,如果stack2为空则将stack1所有的元素存入stack2,否则直接从stack2进行pop(不必再存回stack1)

 

binary tree level order traversal: https://leetcode.com/problems/binary-tree-level-order-traversal/

用一个queue存储树的节点。当queue不为空时记录下当前queue的size,用一个for循环依次pop出queue中的元素,将相应的值push_back进一个临时的vector名为tmp_result,如果有必要的话将新的节点入队。for循环结束后将tmp_result加入result,并将tmp_result进行clear

这道题还有一个解法是用preorder遍历,使用一个单独的递归函数,将depth作为输入的参数,每到新的一层向result中push_back一个新的vector,如果不是新的一层就将数据push_back到对应result编号的vector中去

(DFS,详细参考 https://leetcode.com/discuss/15521/one-of-c-solutions-preorder)

 

palindrome linked list: https://leetcode.com/problems/palindrome-linked-list/

找到链表的中间,然后将后半链表reverse,然后与前半链表进行比对并同时恢复链表

 

first bad version: https://leetcode.com/problems/first-bad-version/

只要对mid调用isBadVersion()。需要注意的是求mid时要用head + (tail - head) / 2而不是(head + tail) / 2,否则可能会溢出。另外mid如果是false的话记得head = mid + 1以避免死循环出现

 

min stack: https://leetcode.com/problems/min-stack/

创建另一个stack存放最小值。在push时,如果当前值<=getMin(),则将其push入存放最小值的stack。注意要使用"<="因为最小值可能出现多次

 

rotate array: https://leetcode.com/problems/rotate-array/

1)时间O(n),空间O(n):创建一个同样大小的vector

2)时间O(n),空间O(n):将原vector的前n - k个元素添加到一个新vector中,erase原vector的前n - k个元素,然后将新数组insert到原数组的后面

3)时间O(n),空间O(1):方法同2),不过逐个地将erase的元素push_back到原vector的最后

4)时间O(n),空间O(1):先reverse前n - k个元素,再reverse后k个元素,最后reverse所有元素

5)时间O(n),空间O(1):改变当前位置对应的所在新位置的元素,然后将当前位置设为新的位置,依次类推逐个地改变所有元素。需要注意的是如果k是n的约数则会出现重复,当出现重复时,将当前位置向后移动一个。这里可以用两个嵌套的循环,外循环处理重复的情况:用一个变量count记录已处理的元素个数,每次令 i = (i + 1) % size,在count < k时进行循环;内循环用do-while,用一个start记录rotate的起点,在(i != start)时进行循环

6)时间O(n),空间O(1):将前k个元素与后k个元素交换,这样数组的前k个位置就是正确的了,然后再对后n - k个元素进行同样的操作直到k变为0,注意每次要处理的数组长度变小,相应的k也要重新对新的长度取余

 

string to integer: https://leetcode.com/problems/string-to-integer-atoi/

判断overflow最好的方法:(value > INT_MAX / 10) || (value == INT_MAX / 10 && str[i] - '0' > INT_MAX % 10)

 

 

Paint Fence: https://leetcode.com/problems/paint-fence/

设两个数组diff和same,分别表示第 i 个位置最后两个post颜色相同和颜色不同的组合数,则diff[i] = (k - 1) * diff[i - 1] + (k - 1) * same[i - 1],same[i] = diff[i - 1],最后返回diff[n - 1] + same[n - 1]即可。可以用四个变量将空间复杂度优化为O(1)

 

Maximum Size Subarray Sum Equals k: https://leetcode.com/problems/maximum-size-subarray-sum-equals-k/

使用一个名为sum的unordered_map,以从头累加到当前位置的和为key,存储当前的位置。如果当前位置 i 的累加和cur_sum == k,则max_len = i + 1,否则寻找cur_sum - k是否在sum中,如果存在,则max_len = max(max_len, i - sum[cur_sum - k])。每次检查cur_sum在不在sum中,如果不在则插入。这里只要在cur_sum第一次出现时插入sum因为这样能保证subarray是最长的

 

Word Pattern: https://leetcode.com/problems/word-pattern/

建立两个unordered_map分别记录pattern和str的对应关系,一边遍历两个输入一边建立,注意substr函数要求起始位置必须是合法的,所以最外层for循环的结束条件应该对两个输入的位置是否合法进行判断,因为要保证pattern的char数和str和word数必须一致,所以最后还应该判断是不是二者都>= .size()了

 

Maximum Subarray: https://leetcode.com/problems/maximum-subarray/

1) 将0 - i 的sum存在nums[i]里,则最大子数列是result = max(result, nums[i] - min_value),min_value是nums[i]在0 ~ i - 1 的最小值,初始化为0

2) dp:max[i] = max(nums[i], nums[i] + max[i - 1]),即以当前位置为结尾的最大子数列可以用或不用当前位置以前的sum。这里不需要一个max[n],只要用一个变量表示max[i - 1]即可

3) 使用divide and conquer方法的思路是,将数组从中间分成两个子数列,分别求每个子数列的:从最左侧开始的最大和数列lmax,从最右侧向左开始的最大和数列rmax,数列所有元素的和sum和数列的最大子数列mx。则当前数列的最大子数列mx可能是mx1,mx2或rmax1 + lmax2;lmax是max(lmax1, sum1 + lmax2),rmax是max(rmax2, rmax1 + sum2)

 

 

算法题

happy number: https://leetcode.com/problems/happy-number/

 

如果结果存在非1的循环,则不是happy number,所以可以通过检查结果是否存在循环来判断。一个可用的cycle detection算法是Floyd algorithm(也叫Tortoise and hare algorithm)。思想是设置两个指针p1,p2。p1一次移动一个单位,p2一次移动两个单位,当p1 == p2时表示循环出现。如果此时的值是1,则返回true,否则返回false。算法详情参考https://en.wikipedia.org/wiki/Cycle_detection,实现详情参考https://leetcode.com/discuss/33055/my-solution-in-c-o-1-space-and-no-magic-math-property-involved

这道题还有一个解法就是用hash table,不断计算下一个值,检查这个值在hash table中是否存在,如果不存在则插入;如果存在检查结果是不是1,如果是1则返回true,否则返回false

 

 

数学技巧题

 

Nim Game: https://leetcode.com/problems/nim-game/

 

n是4的倍数时一定失败

 

add digits: https://leetcode.com/problems/add-digits/

return 1 + (num - 1) % 9;

 

Factorial Trailing Zeros: https://leetcode.com/problems/factorial-trailing-zeroes/

返回5^1的个数 + 5^2的个数 + ... + 5^i的个数,其中5^(i+1) > n。从n开始依次÷5倒着往下比较快,并且保证数据不会溢出

 

 

奇技淫巧题

 

 

move zeros: https://leetcode.com/problems/move-zeroes/

找到第一个0,记录0的个数为count,将 a[i+count] 移动到 a[i]。可以理解为设定了两个指针

 

Roman to integer: https://leetcode.com/problems/roman-to-integer/

判断prev和current的关系

 

ugly number: https://leetcode.com/submissions/detail/43018831/

约去num中所有的2、3、5因数,如果结果为1则返回true,否则返回false。实际约去所有的2、3、5之后如果num不为1,则说明有除2、3、5之外的质因数

 

intersection of two linked list: https://leetcode.com/submissions/detail/45376303/

先计算两个list的长度差为diff,然后让长的cursor先前进diff步,然后让两个list每次都前进一步,则如果二者有intersection则两个cursor会相等。(这个想法来自于如果只判断相等的话,只要判断两个list的最后一个节点是否相同即可)

另一个比较奇技淫巧的方法是设两个指针分别指向两个list,当指针移动到list的结尾后再指向另一个list,两个指针最终会指向第一个intersection的node

 

rectangle area: https://leetcode.com/problems/rectangle-area/

超级傻逼。

 

isomorphic strings: https://leetcode.com/problems/isomorphic-strings/

定义两个256长度的数组并初始化为0,同时遍历两个字符串,每次先检查当前字符上一次出现的位置是否相同,若不同返回false,若相同则更新该字符的出现位置

 

range sum query: https://leetcode.com/submissions/detail/47164891/

将前n个数的和存在private的vector中。注意要在vector的最前面加一个0

 

Missing Ranges: https://leetcode.com/problems/missing-ranges/submissions/

处理起来可能比较messy,一个比较elegant的方法是用一个start记录要创建的range的头,然后用head_idx和tail_idx来记录nums中连续的数字的下标,则每次要创建的range就是[start, nums[head_idx] - 1]。注意这里tail_idx会指向连续数字结尾的后一个位置。start初始化为lower,只要保证所创建的range的头<=尾即可解决第一个range要不要从lower开始的问题。loop结束后单独判断一下nums.back()和upper的关系就知道要不要创建一个以upper为尾的range。注意要单独处理一下nums为空的情况

 

以上是关于Easy题目总结的主要内容,如果未能解决你的问题,请参考以下文章

HDU - 5008 Boring String Problem(后缀树求本质不同第k大子串)

Easy题目总结

Leetcode解题思路总结(Easy篇)

题目过百,是时候发一个阶段性总结了

2021-10-22刷题总结

An easy problem (位运算)