面试题 01.01. 判定字符是否唯一
面试题 01.01. 判定字符是否唯一
实现一个算法,确定一个字符串 s 的所有字符是否全都不同。
示例 1:
输入: s = “leetcode”
输出: false
示例 2:
输入: s = “abc”
输出: true
set去重比较长度
/**
* @param {string} astr
* @return {boolean}
*/
var isUnique = function(astr) {
return new Set(astr).size==astr.length
};
散列思想
/**
* @param {string} astr
* @return {boolean}
*/
var isUnique = function(astr) {
let obj = {}
for (let i of astr) {
if (obj[i]) {
return false
} else {
obj[i] = 1
}
}
return true
}
首次出现和末尾出现的index是否一致
/**
* @param {string} astr
* @return {boolean}
*/
var isUnique = function(astr) {
for (let i of astr) {
if (astr.indexOf(i) !== astr.lastIndexOf(i)) {
return false
}
}
return true
}
面试题 01.02. 判定是否互为字符重排
面试题 01.02. 判定是否互为字符重排
给定两个字符串 s1 和 s2,请编写一个程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。
示例 1:
输入: s1 = “abc”, s2 = “bca”
输出: true
转换数组之后排序在转字符串比对(减少循环次数!!)
/**
* @param {string} s1
* @param {string} s2
* @return {boolean}
*/
var CheckPermutation = function(s1, s2) {
return s1.split('').sort().join('')==s2.split('').sort().join('')
};
哈希字符计数法
没看懂,就知道计数但是怎么比较位置的,而且需要2次循环
/**
* @param {string} s1
* @param {string} s2
* @return {boolean}
*/
var CheckPermutation = function(s1, s2) {
const counter = {};
// 扫描 s1 的字符记数
for(var c of s1){
if(!counter[c]) {
counter[c] = 1;
}else{
counter[c]++;
}
}
// 扫描 s2 的字符
for(var c of s2){
if(!counter[c]) {
// 没在 s1 中出现过,或数量比 s1 多,则跳出
return false;
}else{
// 记数减一
counter[c]--;
// 减空移除 key
if(counter[c] === 0){
delete counter[c];
}
}
}
// 扫描完如果计数器中没全部清零,则证明不能同等变换
return Object.keys(counter).length === 0;
};
面试题 01.03. URL化
URL化。编写一种方法,将字符串中的空格全部替换为%20。假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的“真实”长度。
输入:"Mr John Smith ", 13
输出:“Mr%20John%20Smith”
补充知识点:
1.自带API 解法,js开始作为浏览器的脚本语言,对于URL的编码问题准定是自带API的。但是API有三个,分别是
escape()、encodeURI()、encodeURIComponent()
escape()—— console.log((escape(“http://www.w3school.com.cn/My first/”)));//http%3A//www.w3school.com.cn/My%20first/
encodeURI()——>console.log((encodeURI(“http://www.w3school.com.cn/My first/”))); // http://www.w3school.com.cn/My%20first/
encodeURIComponent()——>console.log((encodeURIComponent(“http://www.w3school.com.cn/My first/”)));
// http%3A%2F%2Fwww.w3school.com.cn%2FMy%20first%2F
2.String.slice、String.substring和String.substr()之间的区别
slice和substring接收的是起始位置和结束位置(不包括结束位置),而substr接收的则是起始位置和所要返回的字符串长度
var test = ‘hello world’;
console.log(test.slice(4,7)); //o w
console.log(test.substring(4,7)); //o w
console.log(test.substr(4,7)); //o world
slice会将它字符串的长度与对应的负数相加,结果作为参数;substr则仅仅是将第一个参数与字符串长度相加后的结果作为第一个参数;substring则干脆将负参数都直接转换为0
var replaceSpaces = function(S, length) {
return encodeURI(S.substring(0,length))
};
var replaceSpaces = function(S, length) {
return S.substr(0,length).split(" ").join("%20");
};
var replaceSpaces = function(S, length) {
return S.substr(0, length).replace(/\s/g, '%20')
};
面试题 01.04. 回文排列
给定一个字符串,编写一个函数判定其是否为某个回文串的排列之一。
回文串是指正反两个方向都一样的单词或短语。排列是指字母的重新排列。
回文串不一定是字典当中的单词。
输入:“tactcoa”
输出:true(排列有"tacocat"、“atcocta”,等等)
思路:回文可定是只有一个单数其他的都能成对或者都能成对,可先删除成对的之后判断剩余的长度是否是小于等于1的
/**
* @param {string} s
* @return {boolean}
*/
var canPermutePalindrome = function(s) {
let obj={}
for(let i=0;i<s.length;i++){
let char=s[i]
if(obj[char]){
delete obj[char]
}else{
obj[char]=1
}
}
return Object.keys(obj).length<=1
};
/**
1. @param {string} s
2. @return {boolean}
*/
var canPermutePalindrome = function(s) {
let obj=new Set()
for(let i=0;i<s.length;i++){
let char=s[i]
if(obj[char]){
delete obj[char]
}else{
obj[char]=1
}
}
return Object.keys(obj).length<=1
};
面试题 01.05. 一次编辑
字符串有三种编辑操作:插入一个字符、删除一个字符或者替换一个字符。 给定两个字符串,编写一个函数判定它们是否只需要一次(或者零次)编辑。
输入:
first = “pale”
second = “ple”
输出: True
补充知识点
Math.abs() 数字取绝对值(负数转换成正数)
Arrary.form:将数据转换成真正的数组
splice对数组进行新增修改删除的操作,改变原数组;
/**
* @param {string} first
* @param {string} second
* @return {boolean}
*/
var oneEditAway = function(first, second) {
//长度分为多一个,少一个,相等(只有一个不同)
var diff =first.length-second.length
if(Math.abs(diff)>1){
return false
}
var maxLength = diff>0?first.length:second.length
var fArray = Array.from(first)
var sArray = Array.from(second)
for(var i =0;i<maxLength;i++){
if(fArray[i]!==sArray[i]){
if(diff===0){
sArray.splice(i,1,fArray[i])
}else if(diff>0){
sArray.splice(i,0,fArray[i])
}else{
fArray.splice(i,0,sArray[i])
}
break;
}
}
return fArray.join() === sArray.join()
};
面试题 01.06. 字符串压缩
字符串压缩。利用字符重复出现的次数,编写一种方法,实现基本的字符串压缩功能。比如,字符串aabcccccaaa会变为a2b1c5a3。若“压缩”后的字符串没有变短,则返回原先的字符串。你可以假设字符串中只包含大小写英文字母(a至z)。
输入:“aabcccccaaa”
输出:“a2b1c5a3”
解题思路:
arr[i]记录当前字符,j记录字符个数;当 当前字符不等于移动的字符时,记录到空字符串中!!!
/**
* @param {string} S
* @return {string}
*/
var compressString = function(S) {
let arr=[...S],str=""
for(let i=0,j=0;j<arr.length;j++){
if(arr[j+1]!=arr[i]){
str+=arr[i]+(j+1-i)
i=j+1
}
}
return str.length<S.length?str:S
}
面试题 01.07. 旋转矩阵
给你一幅由 N × N 矩阵表示的图像,其中每个像素的大小为 4 字节。请你设计一种算法,将图像旋转 90 度。
不占用额外内存空间能否做到?
给定 matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],
原地旋转输入矩阵,使其变为:
[
[7,4,1],
[8,5,2],
[9,6,3]
]
大佬们优秀的思路:
/**
* @param {number[][]} matrix
* @return {void} Do not return anything, modify matrix in-place instead.
*/
var rotate = function(matrix) {
// 不符合题意的个人解法
// let arr=JSON.parse(JSON.stringify(matrix))
// let len =matrix.length
// for(let i=0;i<len;i++){
// for(let j=0;j<len;j++){
// matrix[i][j]=arr[len-j-1][i]
// }
// }
// return arr
let len = matrix.length
for(let i=0;i<len;i++){
for(let j=i+1;j<len;j++){
[matrix[i][j],matrix[j][i]]=[matrix[j][i],matrix[i][j]]
}
matrix[i]=matrix[i].reverse()
}
return matrix
};
面试题 01.08. 零矩阵
编写一种算法,若M × N矩阵中某个元素为0,则将其所在的行与列清零。
输入:
[
[1,1,1],
[1,0,1],
[1,1,1]
]
输出:
[
[1,0,1],
[0,0,0],
[1,0,1]
]
知识点——数组初始化
new Array().fill()的用法
const data=new Array(5)
console.log(data) //(5) [empty × 5]
const data1 = new Array(5).fill()
console.log(data1) // (5) [undefined, undefined, undefined, undefined, undefined]
/**
* @param {number[][]} matrix
* @return {void} Do not return anything, modify matrix in-place instead.
*/
var setZeroes = function(matrix) {
const [m,n]=[matrix.length,matrix[0].length]
let row = new Array(m).fill(false);
let col= new Array(n).fill(false);
for(let i=0;i<m;i++){
for(let j=0;j<n;j++){
if(matrix[i][j]==0){
row[i]=true
col[j]=true
}
}
}
for(let i=0;i<m;i++){
for(let j=0;j<n;j++){
if(row[i]||col[j]){
matrix[i][j]=0
}
}
}
return matrix
};
面试题 01.09. 字符串轮转
字符串轮转。给定两个字符串s1和s2,请编写代码检查s2是否为s1旋转而成(比如,waterbottle是erbottlewat旋转后的字符串)。
输入:s1 = “waterbottle”, s2 = “erbottlewat”
输出:True
知识点
es6 字符串方法
- 字符串重复
let s1=“abc”
s1.repeat(3) //重复3次 “abcabcabc”- 字符串中子串识别
includes() //返回结果是布尔值
includes方法有两个个参数,第一个是要搜索的文本,第二个参数可选,开始搜索的位置的索引值!
/**
* @param {string} s1
* @param {string} s2
* @return {boolean}
*/
var isFlipedString = function(s1, s2) {
//将s1重复两次,可以用es6字符串的 repeat()方法重复!!
return s1.length==s2.length&&s1.repeat(2).includes(s2)
};
面试题 02.01. 移除重复节点
编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。
输入:[1, 2, 3, 3, 2, 1]
输出:[1, 2, 3]
知识盲区需要扫盲!!!
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var removeDuplicateNodes = function(head) {
//这一到链表就不会 哭唧唧
if(!head)return head
let set=new Set()
set.add(head.val)
let [per,cur]=[head,head.next]
while(cur){
if(set.has(cur.val)){
per.next=cur.next
}else{
set.add(cur.val)
per=per.next
}
cur=cur.next
}
return head
};
面试题 02.02. 返回倒数第 k 个节点
实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。
注意:本题相对原题稍作改动
输入: 1->2->3->4->5 和 k = 2
输出: 4
快慢指针
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} k
* @return {number}
*/
var kthToLast = function(head, k) {
let [fast,slow]=[head,head]
while(k--){
fast=fast.next
}
while(fast){
fast=fast.next
slow=slow.next
}
return slow.val
};
数组遍历
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} k
* @return {number}
*/
var kthToLast = function(head, k) {
let arr=[]
while(head){
arr.push(head.val)
head=head.next
}
return arr[arr.length-k]
};
面试题 02.03. 删除中间节点
若链表中的某个节点,既不是链表头节点,也不是链表尾节点,则称其为该链表的「中间节点」。
假定已知链表的某一个中间节点,请实现一种算法,将该节点从链表中删除。
例如,传入节点 c(位于单向链表 a->b->c->d->e->f 中),将其删除后,剩余链表为 a->b->d->e->f
输入:节点 5 (位于单向链表 4->5->1->9 中)
输出:不返回任何数据,从链表中删除传入的节点 5,使链表变为 4->1->9
不会是原罪
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} node
* @return {void} Do not return anything, modify node in-place instead.
*/
var deleteNode = function(node) {
node.val=node.next.val
console.log(node.val,node.next.val) //1,1
node.next=node.next.next
console.log(node.next,node.next.next) //9 null
};