程序员面试金典

面试题 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 字符串方法

  1. 字符串重复
    let s1=“abc”
    s1.repeat(3) //重复3次 “abcabcabc”
  2. 字符串中子串识别
    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
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《C语言程序员面试宝典》是一本专门为C语言程序员准备的面试指南。该书内容涵盖了面试的各个方面,从面试准备、常见问题到专业知识和编程技巧等等。这本书的问答形式非常实用,有助于读者全面了解面试所需的知识和技巧。 首先,《C语言程序员面试宝典》介绍了面试准备阶段应该注意的事项。书中强调了对企业的了解,以及对岗位需求的分析。对于简历的准备和修改也给出了一些指导意见。同时,书中还提供了一些常见面试问题及其答案,帮助读者在面试中更加自信和准备充分。 其次,《C语言程序员面试宝典》逐个章节介绍了C语言常见的面试问题和解决方案。这些问题包括基础知识、数据结构、算法、内存管理、指针、函数等等。每个问题都有相应的解答及其解析,帮助读者理解问题的本质和解决思路。通过逐个问题的介绍,读者可以系统性地学习C语言的知识和技巧。 最后,《C语言程序员面试宝典》还提供了一些编程实例和代码片段,帮助读者更好地掌握C语言的编程技巧。编程实例包括一些常见的算法和数据结构实现,读者可以通过阅读和实践这些例子来提高自己的编程能力。 总的来说,《C语言程序员面试宝典》是一本非常实用的面试指南,适合C语言程序员准备面试使用。通过阅读和学习这本书,读者可以全面提升自己的面试能力,增加成功的机会。无论是对于初入职场的程序员还是有一定经验的程序员,这本书都是一本值得阅读的好书。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值