忽然意识到leetcode是不存本身写的代码的,都是临时存在本地而已,若是本身清理垃圾,估计会直接被清除掉。但本身的一些想法会写在代码里,仍是把代码搬了过了。有想过弄去github的,可是感受这里会方便一点,先弄在这里吧。javascript
如下是9.6-9.13作过的题目java
目录node
1160. 拼写单词github
160. 相交链表 数组
给定仅有小写字母组成的字符串数组 A,返回列表中的每一个字符串中都显示的所有字符(包括重复字符)组成的列表。例如,若是一个字符在每一个字符串中出现 3 次,但不是 4 次,则须要在最终答案中包含该字符 3 次。
你能够按任意顺序返回答案。
示例 1:
输入:["bella","label","roller"]
输出:["e","l","l"]
示例 2:输入:["cool","lock","cook"]
输出:["c","o"]
题解:https://leetcode-cn.com/problems/find-common-characters/solution/js-by-blzbanme/
这题的解法三用了filter,不太懂。filter会返回return true的元素组成的数组,但下面这行代码,实在巧妙,我有点暂时接受不了。个人疑问是,temp[index] = 1这个,也算true的表达??
return index !== -1 ? temp[index] = 1 : false;
/** * @param {string[]} A * @return {string[]} */ var commonChars = function(A) { let res = A[0].split(""); for(let i = 1; i < A.length; i++){ let temp = A[i].split(""); res = res.filter(e => { let index = temp.indexOf(e); return index !== -1 ? temp[index] = 1 : false; }); } return res; };
给定两个字符串 s 和 t ,编写一个函数来判断 t 是不是 s 的字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram"
输出: true
示例 2:输入: s = "rat", t = "car"
输出: false
/** * @param {string} s * @param {string} t * @return {boolean} */ var isAnagram = function(s, t) { let res = s.split(""); let temp = t.split(""); if(res.length !== temp.length)return false;//这句话仍是很是有用的。直接为后面不论是用哈希仍是其余都省去很多麻烦 return res.every(e => { let index = temp.indexOf(e); return index !== -1? temp[index] = 1 : false; }); };
上面那个是我本身用的方法,跟1002那道题同样,为何那道题运行速度还行而这个运行速度直接飙2000ms?
其余人的解法:https://leetcode-cn.com/problems/valid-anagram/solution/you-xiao-de-zi-mu-yi-wei-ci-by-chitanda-eru/
1.是用哈希表,记录次数。若是第一次记录则将次数设为1,若自己已有次数,则在其基础上+1。记录完次数时候,比较s和t的哈希表
let char in对象的话,char表示的是属性。
2.用sort排序完以后一一匹配,但有一个相似的更简便的是:(这个甚至不出现for这一个词。用等号就实现了)牛
var isAnagram = function(s, t) { if(s.length != t.length) return false; return s.split('').sort().join('') == t.split('').sort().join(''); }
1.get的用法:返回根据键值检索到的特定的值
2.let newMap = new Map(map);//复制一个map
3.这题可多看
给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars。
假如你能够用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么咱们就认为你掌握了这个单词。
注意:每次拼写时,chars 中的每一个字母都只能用一次。
返回词汇表 words 中你掌握的全部单词的 长度之和。
示例 1:
输入:words = ["cat","bt","hat","tree"], chars = "atach"
输出:6
解释:
能够造成字符串 "cat" 和 "hat",因此答案是 3 + 3 = 6。
示例 2:输入:words = ["hello","world","leetcode"], chars = "welldonehoneyr"
输出:10
解释:
能够造成字符串 "hello" 和 "world",因此答案是 5 + 5 = 10。
/** * @param {string[]} words * @param {string} chars * @return {number} */ var countCharacters = function(words, chars) { let map = new Map(); for(let c of chars){ if(map.has(c)) map.set(c, map.get(c)+1);//get:返回根据键值检索到的特定的值 else map.set(c, 1); } let res = 0; for(let w of words){ let temp = w.split('');//将一个单词拆分红一个个字母储存 if(check(temp,map)) res += temp.length; } return res; function check(word, map){//word是存着单词的数组,map是存着单词和它对应的出现次数的哈希表 let newMap = new Map(map);//复制一个map let back = true; for(let w of word){ if(newMap.has(w) && newMap.get(w) > 0) newMap.set(w, newMap.get(w)-1); else back = false; } return back; } };
删除链表中等于给定值 val 的全部节点。
示例:
输入: 1->2->6->3->4->5->6, val = 6 输出: 1->2->3->4->5
19.9.11
while中的head && head.next是有顺序的。head要在head.next前面。否则,若是head为空,那head.next就会出错。
我!一开始觉得这道题很简单的...没想到后面一直改bug,例子能经过这个就通不过那个,为告终果改代码,改到我本身都不认得了...
/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ /** * @param {ListNode} head * @param {number} val * @return {ListNode} */ // 本身写的,放弃了放弃了 var removeElements = function(head, val) { let apple = head; while(head){ if(head.next === null){ if(head.val === val){ head = null; return head; } head = head.next; } else{ while(head && head.next){ if(head.next.val === val){ head.next = head.next.next; } if(head.next === null)break; head = head.next; //估计个人代码一开始就从这里错掉了 } } } return apple; }; //方法一 var removeElements = function(head, val) { while(head && head.val === val){ head = head.next; //这是将头结点直接挪到下一个节点上去 } if(!head)return head; let pre = head; while(pre && pre.next){//须要加pre && 吗。 仍是加吧,没影响的状况下本身能更好理解 if(pre.next.val === val){ pre.next = pre.next.next; }else{ pre = pre.next;// 首先,不能够去掉原先的else,请看这个栗子[1,2,2,1]2,若是去掉else,在删除完第一个2以后,pre去到了下一个2,它看的是谁?它看的是后面的数了,再也不看本身是否要被删掉。 } } return head; } // 方法二 额外加一个虚拟节点 var removeElements = function(head, val) { let node = new ListNode(val-1); node.next = head; let pre = node; while(pre && pre.next){ if(pre.next.val === val){ pre.next = pre.next.next; }else{ pre = pre.next; } } return node.next; } // 方法三 递归 var removeElements = function(head, val) { if(!head)return null; head.next = removeElements(head.next, val); if(head.val === val){ return head.next; }else{ return head; } }
/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ /** * @param {ListNode} headA * @param {ListNode} headB * @return {ListNode} */ // 方法一 var getIntersectionNode = function(headA, headB) { let pA = headA; let pB = headB; while(pA !== pB){ pA = pA? pA.next : headB; pB = pB? pB.next : headA; } return pA; }; // 先遍历headA并打上标记,再遍历headB寻找标记。 var getIntersectionNode = function(headA, headB) { while(headA){ headA.sep = 1; headA = headA.next; } while(headB){ if(headB.sep) return headB headB = headB.next; } };
给出第一个词 first 和第二个词 second,考虑在某些文本 text 中可能以 "first second third" 形式出现的状况,其中 second 紧随 first 出现,third 紧随 second 出现。
对于每种这样的状况,将第三个词 "third" 添加到答案中,并返回答案。
示例 1:
输入:text = "alice is a good girl she is a good student", first = "a", second = "good"
输出:["girl","student"]
/** * @param {string} text * @param {string} first * @param {string} second * @return {string[]} */ // 为何个人for循环里面的if进不去?!!!明明和题解同样啊?!!! (过了十几分钟终于知道了...开头的split里没有空格 var findOcurrences = function(text, first, second) { let textArr = text.split(''); // let arr = []; let result = []; // arr.push(first, second); // console.log(arr); for(let i = 0; i < textArr.length; i++){ if(textArr[i] == first && textArr[i+1] == second && !!textArr[i+2]){ console.log('hello');//这个没显示、、、 result.push(textArr[i+2]); console.log(result); } } return result; }; var findOcurrences = function(text, first, second) { let textArr = text.split(' '); // let addArr = [] let result = []; // addArr.push(first, second) for(let i = 0; i < textArr.length; i++){ if(textArr[i] == first && textArr[i+1] == second && !!textArr[i+2]){ // console.log('hello'); result.push(textArr[i+2]); } } return result; };
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2 输出: false示例 2:
输入: 1->2->2->1 输出: true
/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ /** * @param {ListNode} head * @return {boolean} */ var isPalindrome = function(head) { if(!head || !head.next)return true; let mid = head, pre,//这个初始化加不加 null都不要紧 reversed = null; while(head && head.next){ pre = mid;//这个赋值要在 mid被修改以前 mid = mid.next; head = head.next.next; pre.next = reversed; reversed = pre; } if(head)mid = mid.next;//① while(mid){ if(mid.val !== reversed.val)return false; mid = mid.next; reversed = reversed.next; } return true; };
①:这个有点厉害。若是链表是奇数个,那退出while循环时,head指向最后一个。但若是是偶数个时,head会指向null。因此用head的指向来判断链表数是奇数仍是偶数。若是是奇数,mid要加1,避开那个对称点
给定一个带有头结点 head 的非空单链表,返回链表的中间结点。
若是有两个中间结点,则返回第二个中间结点。
示例 1:
输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,咱们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ /** * @param {ListNode} head * @return {ListNode} */ //本身的解法...慢的要死 这个仍是基于链表的 var middleNode = function(head) { let apple = head, length = 0, result = head, len; for(; apple != null; apple = apple.next){ length++; } if(length % 2 === 0){ len = length/2; }else{ len = length/2 - 1; //不知道为何要-1。由于我是根据运行结果来调试的,-1的时候结果对了 } for(let i = 0; i < len ; i++){ result = result.next; } return result; }; //解法1:将链表输出到数组,数组的话能够按索引找 ???怎么return是undefined??由于要求的是返回链表,你如今只是把数存进数组了,应该把val和next同时存进数组的,因此用push才正确 var middleNode = function(head) { let result = []; for(let i = 0, apple = head; apple != null; i++, apple = apple.next){ // result[i] = apple.val;//这句话错了 result.push(apple); } // console.log(result); // console.log(result.length); // console.log (result.slice(Math.floor(result.length/2))); // return Array.from(result); // console.log(5/2);//2.5 return result[Math.floor(result.length/2)];//注意了!下标直接用result.length/2是不行的,会直接返回undefined,由于目前的测试代码的长度为5,5/2=2.5而下标是没有2.5的,必定要用floor或者trunc方法对数据进行处理 } // var middleNode = function(head) { // let A = [head]; // while (A[A.length - 1].next != null) // A.push(A[A.length - 1].next); // return A[Math.trunc(A.length / 2)]; // }; // 解法2 快慢指针 68ms var middleNode = function(head) { let slow = fast = head; while(fast && fast.next != null){ //为何去掉fast 就会报错? 由于必定要检测fast.next是否为空,因此也要检测fast,由于若是fast为空,fast.next是会出错的。 // console.log(slow.val +" "+fast.val); slow = slow.next; fast = fast.next.next;//用到fast.next.next,因此要看一下fast.next是否为空,由于若是fast.next为空,fast.next.next是会出错的 } return slow; }
给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。
对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。
你能够返回任何知足上述条件的数组做为答案。
示例:
输入:[4,2,5,7]
输出:[4,5,2,7]
解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。
初版:我以为要用到splice
**官方题解:**(有点相似快排的一部分,用了双链表)
一旦全部偶数都放在了正确的位置上,那么全部奇数也必定都在正确的位子上。因此只须要关注 A[0], A[2], A[4], ... 都正确就能够了。
将数组分红两个部分,分别是偶数部分 even = A[0], A[2], A[4], ... 和奇数部分 odd = A[1], A[3], A[5], ...。定义两个指针 i 和 j, 每次循环都须要保证偶数部分中下标 i 以前的位置全是偶数,奇数部分中下标 j 以前的位置全是奇数。
**算法**
让偶数部分下标 i 以前的全部数都是偶数。为了实现这个目标,把奇数部分做为暂存区,不断增长指向奇数部分的指针,直到找到一个偶数,而后交换指针 i,j 所指的数。
第二版:最外层的for循环好奇怪。写不出不想要的感受。一写就会多访问数组外的值。
算是初步改好了,还剩数组调换那里,不想再补了。知道怎么补,可是补了以后代码看起来就会很臃肿。算了,跳坑写第三版
第三版:写完了
/** * @param {number[]} A * @return {number[]} */ // 初版:本身写的时候卡掉了... // var sortArrayByParityII = function(A) { // let odd = []; // A.forEach((item, index) => { // if(item % 2 !== 0){ // odd.push(item); // // A.splice(index,1); // } // }); // console.log(A); // console.log(odd); // }; // 第二版:只想到快排有一部分类似,可是忽略了它的结束条件。在这道题里,若是按快排的思路,很难写结束条件 // var sortArrayByParityII = function(A) { // // console.log(A.length); // // console.log(A.length/2); // let len = A.length/2; // let i = 0, j = 1;//忘了快排具体的了,我是要用i作外循环,j作内循环吗? // for(let x = 0; x < A.length/2; x++){ // while(A[i] % 2 == 0 && A[i+2] !== undefined)i += 2;//忽然感受本身在挖坑而后跳了进去... // while(A[j] % 2 == 1 && A[j+2] !== undefined)j += 2; // console.log("i:"+i+" "+"j:"+j); // [A[i],A[j]]=[A[j],A[i]];//要添加多一些条件,这样就会变得冗杂,失去原本想简洁的初衷了 // console.log(x +":"+A); // } // return A; // } // 第三版 var sortArrayByParityII = function(A) { let i = 0, j = 1; for(; i < A.length; i += 2){ if(A[i] % 2 == 0)continue; while(A[j] % 2 == 1)j += 2; [A[i],A[j]]=[A[j],A[i]]; } return A; }
给出 R 行 C 列的矩阵,其中的单元格的整数坐标为 (r, c),知足 0 <= r < R 且 0 <= c < C。
另外,咱们在该矩阵中给出了一个坐标为 (r0, c0) 的单元格。
返回矩阵中的全部单元格的坐标,并按到 (r0, c0) 的距离从最小到最大的顺序排,其中,两单元格(r1, c1) 和 (r2, c2) 之间的距离是曼哈顿距离,|r1 - r2| + |c1 - c2|。(你能够按任何知足此条件的顺序返回答案。)
示例 1:
输入:R = 1, C = 2, r0 = 0, c0 = 0
输出:[[0,0],[0,1]]
解释:从 (r0, c0) 到其余单元格的距离为:[0,1]
// 这是参考的代码,比较慢 268ms var allCellsDistOrder = function(R, C, r0, c0) { let result = []; for(let r = 0; r < R; r++){ for(let c = 0; c < C; c++){ let temp = [r,c]; result.push(temp); } } result.sort((a,b) => { let ta = Math.abs(a[0] - r0) + Math.abs(a[1] - c0), tb = Math.abs(b[0] - r0) + Math.abs(b[1] - c0); return ta - tb; }); return result; };
笔记 1. result是二维数组吗? 怎么声明 **解决:** result为一维数组,定义一个是坐标的变量,而后 2. temp那个是数组来的,能够用temp[0]和temp[1]访问。同理,sort里面的那个函数参数a和b也能够用方括号访问 3. sort()仍是不熟:若是想要参数一在参数二以前就返回一个负数。(高程P92