1.15 Get Maximum in Generated Array
You are given an integer n. An array nums of length n + 1 is generated in the following way:
nums[0] = 0
nums[1] = 1
nums[2 * i] = nums[i] when 2 <= 2 * i <= n
nums[2 * i + 1] = nums[i] + nums[i + 1] when 2 <= 2 * i + 1 <= n
Return the maximum integer in the array nums.
题解:
var getMaximumGenerated = function(n) {
let k=[0,1];
if(n<=0) return k[0];
for(let i=1;i<n;i++){
if((2*i)<=n && (2*i+1)<=n){
k[2*i]=k[i];
k[2*i+1]=k[i]+k[i+1];
}
}
return Math.max(...k);
};
水题,维护一个数组k,根据题目的规则生成数组元素,最后取最大值
1.16 Kth Largest Element in an Array
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
Example 1:
Input: [3,2,1,5,6,4] and k = 2
Output: 5
Example 2:
Input: [3,2,3,1,2,4,5,5,6] and k = 4
Output: 4
很有意思的题目,当时一看到的时候就想到堆排序(没有具体的原因,可能就是因为以前碰过类似这样用堆的题目),但是由于使用的是js,没有python那样内置的heap,所以一开始没有用堆排序
function mergeSort(nums){
if (nums.length<2) return nums
let left = [];
let right = [];
let mid = nums[0];
for (let i = 1;i<nums.length;i++){
nums[i]<mid?left.push(nums[i]):right.push(nums[i])
}
return [...mergeSort(left),mid,...mergeSort(right)]
}
var findKthLargest = function(nums, k) {
return mergeSort(nums)[nums.length-k]
};
以上代码思路为快速排序(我一查发现混淆了快速排序和归并排序,一直把归并排序当成快速排序了)后,取第k大的元素,虽然应该不是最优解,但是应该也是不错的方法,提交后结果:
//输入为 [0,1,...,4999],1 时
//FATAL ERROR: Scavenger: semi-space copy Allocation failed - JavaScript heap out of memory
这个报错非常有意思,JavaScript堆内存溢出,让我去好好了解了一遍js堆栈存储juejin.cn/post/684490…,这个案例下,mergeSort了[0,1,...,4999]这个数组,执行了4999次mergeSort(right),也创建了这么多层的闭包,在堆中创造了大量的[[SCOPE]],最终导致堆内存溢出。
贴一个与堆排序差不多的方法,用了优先队列,js中实现优先队列和heap都要花点时间,优先队列代码短一点
function PriorityQueue (){
collections = [];
this.enqueue = function(priority){
if(!collections.length){
collections.push(priority);
}else{
let added = false;
for(let i = 0;i< collections.length;i++){
if(collections[i] < priority){
collections.splice(i,0,priority);
added = true;
break;
}
}
if(!added){
collections.push(priority);
}
}
}
this.dequeue = function(){
if(collections.length)
collections.pop();
}
this.size = function() {
return collections.length;
}
this.getQueue = function(){
return collections;
}
}
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var findKthLargest = function(nums, k) {
let priorityQ = new PriorityQueue();
for(let n of nums){
priorityQ.enqueue(n);
if(priorityQ.size() > k){
priorityQ.dequeue();
}
}
const list = priorityQ.getQueue();
return(list[list.length -1]);
};
1.17 Count Sorted Vowel Strings
Given an integer n, return the number of strings of length n that consist only of vowels (a, e, i, o, u) and are lexicographically sorted.
A string s is lexicographically sorted if for all valid i, s[i] is the same as or comes before s[i+1] in the alphabet.
Example 1:
Input: n = 1
Output: 5
Explanation: The 5 sorted strings that consist of vowels only are ["a","e","i","o","u"].
Example 2:
Input: n = 2
Output: 15
Explanation: The 15 sorted strings that consist of vowels only are
["aa","ae","ai","ao","au","ee","ei","eo","eu","ii","io","iu","oo","ou","uu"].
Note that "ea" is not a valid string since 'e' comes after 'a' in the alphabet.
Example 3:
Input: n = 33
Output: 66045
简而言之,找到长度为n的字符串的个数,要求这些字符串内部一定要有a、e、i、o、u的顺序,不能有..ea...这样的字符串存在
function sum(arr){
return arr.reduce((a,b)=>{return a+b},0)
}
function backtrack(vowels,n){
if(n>1){
n--;
return backtrack([sum(vowels),sum(vowels.slice(1)),sum(vowels.slice(2)),sum(vowels.slice(3)),1],n);
}else{
return sum(vowels)
}
}
var countVowelStrings = function(n) {
return backtrack([1,1,1,1,1],n)
};
思路:如果把以a、e、i、o、u开头的字符串个数记为a[n],e[n],i[n],o[n],u[n],则它们满足这样的关系
a[n+1] = a[n]+e[n]+i[n]+o[n]+u[n];
e[n+1] = e[n]+i[n]+o[n]+u[n];
i[n+1] = i[n]+o[n]+u[n];
o[n+1] = o[n]+u[n];
u[n+1] = u[n];
所以使用动态规划,从1求到n
看了一波别人的题解,有一些更为精妙的dp方法(python,java,c++),用js再敲一遍
// 1维DP
var countVowelStrings = function(n) {
let dp = [0,1,1,1,1,1];
n++;
while(n){
n--;
for (let i=1;i<6;i++){
dp[i] += dp[i-1]
}
}
return backtrack([1,1,1,1,1],n)
};
// 组合数
var countVowelStrings = function(n) {
return (n+1)*(n+2)*(n+3)*(n+4)/24
};
1.18 Max Number of K-Sum Pairs
You are given an integer array nums and an integer k.
In one operation, you can pick two numbers from the array whose sum equals k and remove them from the array.
Return the maximum number of operations you can perform on the array.
Example 1:
Input: nums = [1,2,3,4], k = 5
Output: 2
Explanation: Starting with nums = [1,2,3,4]:
- Remove numbers 1 and 4, then nums = [2,3]
- Remove numbers 2 and 3, then nums = []
There are no more pairs that sum up to 5, hence a total of 2 operations.
Example 2:
Input: nums = [3,1,3,4,3], k = 6
Output: 1
Explanation: Starting with nums = [3,1,3,4,3]:
- Remove the first two 3's, then nums = [1,4,3]
There are no more pairs that sum up to 6, hence a total of 1 operation.
一开始自己写的题解,用字典来存储数组里数字出现频率,
var maxOperations = function(nums, k) {
let dict = {},copy = [...nums],delCount = 0,cnt=0;
for(let i=0;i<nums.length;i++){
if(k-nums[i]>0){
if(dict[nums[i]]){
dict[nums[i]] += 1
}else{
dict[nums[i]]=1
}
}else{
copy.splice(i-delCount,1);
delCount++;
}
}
for(let i of copy){
if(dict[k-i]){
dict[k-i] -= 1;
if(dict[i]){
dict[i] -= 1;
cnt++;
}
}
}
return cnt
};
accepted后看其他js题解多使用了Map,虽然Map与dict使用上区别不大,但实践上比一般的dict确实要优雅高效些(developer.mozilla.org/zh-CN/docs/…
const getRecord2 = (arr) => {
let map = new Map();
for (const i of arr) {
map.set(i, (map.get(i) + 1) || 1);
}
return map;
};
const maxOperations = (nums, k) => {
let map = getRecord2(nums); // each num occurrence map
let res = 0;
for (const x of map.keys()) {
if (map.has(k - x)) {
res += Math.min(map.get(x), map.get(k - x));
}
}
return res >> 1;
};
1.19 Longest Palindromic Substring
Given a string s, return the longest palindromic substring in s.
Example 1:
Input: s = "babad"
Output: "bab"
Note: "aba" is also a valid answer.
Example 2:
Input: s = "cbbd"
Output: "bb"
Example 3:
Input: s = "a"
Output: "a"
Example 4:
Input: s = "ac"
Output: "a"
本题找最长的回文,有一个很火的讨论 leetcode.com/explore/cha… 用js改写了一下
var longestPalindrome = function(s) {
let len = s.length;
if (len <= 1) return s;
let lpos = 0, lm = 0; // 回文开始处与回文长度
for ( let i = 0; i < len - 1; i++) {
if (lm >= (len - i) * 2) return s.substring(lpos,lpos+lm); //类似剪枝优化
let count = 0;
while (s[i + 1] === s[i] && i++ < len - 1)
count++; //如果有一样的元素,直接从这些元素的头尾开始找
let end = i, first = i - count;
while (s[--first] == s[++end] && first >= 0 && end < len);
end--;
first++; //找到字符串两端不相等为止,前后各回退一格
if ( lm < end - first + 1){ //与之前最长回文长度比较
lpos = first;
lm = end - first + 1;
}
}
return s.substring(lpos, lpos+lm);
}
todo:DP
1.20 Valid Parentheses
Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
An input string is valid if:
Open brackets must be closed by the same type of brackets. Open brackets must be closed in the correct order.
Example 1:
Input: s = "()"
Output: true
Example 2:
Input: s = "()[]{}"
Output: true
Example 3:
Input: s = "(]"
Output: false
Example 4:
Input: s = "([)]"
Output: false
Example 5:
Input: s = "{[]}"
Output: true
解题很快,扫描元素将左括号入栈,当遇到右括号后出栈匹配
function pair(bracket1,bracket2){
switch(bracket1){
case ')':
return bracket2 === '('
case ']':
return bracket2 === '['
case '}':
return bracket2 === '{'
}
}
var isValid = function(s) {
if (s.length%2) return false
let stack = [];
for (let i of s){
if (['(','[','{'].indexOf(i)!==-1){
stack.push(i);
}else{
let b2 = stack.pop();
if(!pair(i,b2)) return false
}
}
return stack.length === 0
};
可以优化的地方就是可以用Map来替代配对pair函数
let map = new Map([['(',')'],['[',']'],['{','}']]);
// 使用
if(map.get(i)!==stack.pop()) return false
1.21 Find the Most Competitive Subsequence
TODO