每日一题

167 阅读5分钟

前仆后继

删除排序数组中的重复项

/**
 * @param {number[]} nums
 * @return {number}
 */
 /*
 思路在现有的数组数组中进行从前往后查找,如果查到的数组位置与现循环的i不同证明现有循环元素不是第一个,正它有重复项
 */
var removeDuplicates = function(nums) {
    for(let i=0;i<nums.length;i++){
        if(nums.indexOf(nums[i]) !== i){
            nums.splice(i,1);
            //i--的意义就在于,当使用splice 的时候操作的原数组,截取之之后需要减一个,要不将会越过数组下一个元素
            i--;
        }
    }
    return nums.length;
};

知识点: indexOf语法链接

/**
 * @param {item,index} searchElement:查找元素  fromIndex:从数组的index之后的位置查询
 * @return {number}
 */
arr.indexOf(searchElement, fromIndex)

例子1: 可以查询到同一元素在,数组中的位置以及重复数

let str ="index e hajkdh e".split('')
let post = [];
let pos =str.indexOf('e');

while(pos>-1){
    post.push(pos);
    pos = str.indexOf('e', pos+1)
}
console.log(post)

例子2:能够让你惊讶 链接string

"76wenshu".indexOf('')  //0
"76wenshu".indexOf('7') //0

智勇双全

***给定一个数组,将数组中的元素向右移动 k *个位置,其中 k 是非负数

var rotate = function(nums, k) {
      //1.使用for 或者 while
      //for(let i=0;i<k;i++){    
         //nums.unshift(nums.pop())
     // }
     //2.
    return nums.unshift(...nums.splice(nums.length - k))
};

知识点: splice语法链接

无坚不摧

存在重复元素

给定一个整数数组,判断是否存在重复元素。 如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。 示例 1: 输入: [1,2,3,1] 输出: true

/**
 * @param {number[]} nums
 * @return {boolean}
 */
var containsDuplicate = function(nums) {
    return Array.from(new Set(nums)).length!==nums.length

};

知识点:Set 语法链接

坚定自己的信念

只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

输入: [2,2,1]

输出: 1

/**
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function(nums) {
//定义两个变量的原因(https://juejin.cn/post/7004580246208905247)有讲解
        for(let i=0,j=nums.length;i<j; i++){
        //indexOf的方向在上边有讲解,lastIndexOf和indexOf差不多是从后向前查
        //解题的关键就在这里,因为如果在数组或者字符串中,没有重复项那么从后向前和从后向前获取的index都是是相同的
            if(nums.indexOf(nums[i])===nums.lastIndexOf(nums[i])){
                return nums[i]
            }
        }
};

知识点:如何阻止forEach循环

try {
    const  arr = ["76wenshu","心里有火","眼里有光"];
    arr.forEach(function(item,index){
        if (item == "心里有火") {
            throw new Error("心里有火");
        }
        console.log(item);
    });
} catch(e) {
    if(e.message!="心里有火") throw e;
}

如果还需要别的方法,那就需要你头铁可以自己去改数组原型链中非forEach方法。 我觉得没必要纠结这个事情,每个函数都有自己的用途,不要为了钻牛角尖而钻牛角尖。 我喜欢使用for循环我的它快捷方便。

两个数组的交集 II 给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2] 输出:[2,2]

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersect = function(nums1, nums2) {
    const arr = [];
    //思路:循环2数组中的每一项,是否在1数组中存在,如果存在就将它在数组1中去除掉,push到arr中,之后返回。
    {nums2|| []}.forEach(item =>{
    //indexOf可以看上百年的第一题
        if(nums1.indexOf(item)!==-1){
            arr.push(nums1.splice(nums1.indexOf(item),1));
        }
    })
    return arr
};

知识点:findIndex语法知识点

//验证findIndex的第二个参数
    const arr = [1,3,2,4];
    //不能使用尖头函数this解析(https://juejin.cn/post/7005959510116433956)
    (arr||[]).findIndex(function(item){
        console.log(this)//[9,0,8]
        return item ===2; 
    },[9,0,8])

移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

示例:

输入: [0,1,0,3,12] 输出: [1,3,12,0,0]

说明:

必须在原数组上操作,不能拷贝额外的数组。 尽量减少操作次数。

/**
 * @param {number[]} nums
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var moveZeroes = function(nums) {
    for(let i=0,j=nums.length;i<j;i++){
        if(nums[i]===0){
            nums.push(nums.splice(i,1))
            i--
        }
    }
};

反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。 不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

示例 1:

输入:["h","e","l","l","o"] 输出:["o","l","l","e","h"]

/**
 * @param {character[]} s
 * @return {void} Do not return anything, modify s in-place instead.
 */
var reverseString = function(s) {
    return s.reverse()
};

知识点:reverse知识点

重点:

const a = {0: 1, 1: 2, 2: 3, length: 3};

console.log(a); // {0: 1, 1: 2, 2: 3, length: 3}

Array.prototype.reverse.call(a); //same syntax for using apply()

console.log(a); // {0: 3, 1: 2, 2: 1, length: 3}

两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    for(let i=0;i<nums.length;i++){
        if(nums.indexOf(target-nums[i],i+1)!==-1){
            return [i,nums.indexOf(target-nums[i],i+1)]
        }    
    }
};

知识点:如果不理解思路不要问自己想,看看第一题,学习知识最难,就是将学习的知识使用上。

字符串中的第一个唯一字符

给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。

示例:

s = "leetcode" 返回 0

s = "loveleetcode" 返回 2

/**
 * @param {string} s
 * @return {number}
 */
var firstUniqChar = function(s) {
    let sarr = s.split('')
    for(let i=0;i<sarr.length;i++){
        if(s.indexOf(sarr[i])===s.lastIndexOf(sarr[i])){
            return i
        }
    }
    return -1
};

整数反转

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [−231,  231 − 1] ,就返回 0。 假设环境不允许存储 64 位整数(有符号或无符号)。   示例 1:

输入:x = 123 输出:321

/**
 * @param {number} x
 * @return {number}
 */
var reverse = function(x) {
    if(x>=0){
        return Number(String(x).split('').reverse().join(''))>Math.pow(2,31)-1?0:Number(String(x).split('').reverse().join(''))
    }else{
        return -Number(String(x).substring(1).split('').reverse().join(''))<-Math.pow(2,31)?0:-Number(String(x).substring(1).split('').reverse().join(''))
    }
};

铭记历史、勿忘国耻

有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

示例 1:

输入: s = "anagram", t = "nagaram" 输出: true

/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
var isAnagram = function(s, t) {
    return s.split('').sort().join('')===t.split('').sort().join('')? true:false
    
};

数据结构和算法的高度就是你编程的高度

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。  

示例 1:

输入:s = "()" 输出:true

//利用stack的原理实现的解题思路
//通俗的理解就是如果返回true 一定是一半一半的括号值,
//但是就是只判断一半一半是不对的有可能摆放的问题有问题也会有问题那就使用stack来进行实现,
//就是括号对应的就是last in first out的理解进行处理,数据都处理完之后,stack中是不会有值的取反。
//有的就进stack没有就出stack,最后正确就是stack中无数据
var isValid = function(s) {
    //新建一个map对象
    let map = new Map();
    //设置三个key值
    map.set('(',')');
    map.set('{','}');
    map.set('[',']')

    let stack = [];
    for(let i of s){
        //如果 i‘(’ 在 map中 stack[')'] ')' 
        if(map.has(i)) stack.push(map.get(i));
        else{
            //如果 i‘)’ 在 map中 [')']==> []
            if(stack.length === 0 || stack.pop() !== i) return false;
        }
    }
    return !stack.length;
};


//作者:20212021
//链接:https://leetcode-cn.com/problems/valid-parentheses/solution/js20you-xiao-de-gua-hao-map-by-bzxspkcm-w338/

生活没有激情,那就是没有了希望

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

push(x) —— 将元素 x 推入栈中。 pop() —— 删除栈顶的元素。 top() —— 获取栈顶元素。 getMin() —— 检索栈中的最小元素。  

示例:

输入: ["MinStack","push","push","push","getMin","pop","top","getMin"] [[],[-2],[0],[-3],[],[],[],[]]

输出: [null,null,null,null,-3,null,0,-2]

解释: MinStack minStack = new MinStack(); minStack.push(-2); minStack.push(0); minStack.push(-3); minStack.getMin(); --> 返回 -3. minStack.pop(); minStack.top(); --> 返回 0. minStack.getMin(); --> 返回 -2.

//个人理解就是使用数组来实现

var MinStack = function() {
    this.stack = [];
    this.help = [Infinity];
};

/** 
 * @param {numberx
 * @return {void}
 */
MinStack.prototype.push = function(x) {
    this.stack.push(x);
    
};

/**
 * @return {void}
 */
MinStack.prototype.pop = function() {
    
    this.stack.pop();
};

/**
 * @return {number}
 */
MinStack.prototype.top = function() {
    return this.stack[this.stack.length-1];
};

/**
 * @return {number}
 */
MinStack.prototype.getMin = function() {
    let getMin;
    if(this.stack.length===0){
        return null
    }
    for(let i=0;i<this.stack.length; i++){
        if(!getMin && getMin !==0){
            getMin=this.stack[i]
        }else{
            getMin=this.stack[i]<getMin?this.stack[i]:getMin
        }
    } 
return getMin
};

不要在意别人的眼光,做自己想做的

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):

实现 MyQueue 类:

void push(int x) 将元素 x 推到队列的末尾 int pop() 从队列的开头移除并返回元素 int peek() 返回队列开头的元素 boolean empty() 如果队列为空,返回 true ;否则,返回 false  

说明:

你只能使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。  

进阶:

你能否实现每个操作均摊时间复杂度为 O(1) 的队列?换句话说,执行 n 个操作的总时间复杂度为 O(n) ,即使其中一个操作可能花费较长时间。  

示例:

输入: ["MyQueue", "push", "push", "peek", "pop", "empty"] [[], [1], [2], [], [], []] 输出: [null, null, null, 1, 1, false]

var MyQueue = function() {
    this.stack = []

};

/** 
 * @param {number} x
 * @return {void}
 */
MyQueue.prototype.push = function(x) {
    this.stack.push(x)

};

/**
 * @return {number}
 */
MyQueue.prototype.pop = function() {
   return  this.stack.shift()

};

/**
 * @return {number}
 */
MyQueue.prototype.peek = function() {
    return this.stack[0]

};

/**
 * @return {boolean}
 */
MyQueue.prototype.empty = function() {
    return this.stack.length?false:true

};

/**
 * Your MyQueue object will be instantiated and called as such:
 * var obj = new MyQueue()
 * obj.push(x)
 * var param_2 = obj.pop()
 * var param_3 = obj.peek()
 * var param_4 = obj.empty()
 */

糙、快、猛

Alice 有 n 枚糖,其中第 i 枚糖的类型为 candyType[i] 。Alice 注意到她的体重正在增长,所以前去拜访了一位医生。

医生建议 Alice 要少摄入糖分,只吃掉她所有糖的 n / 2 即可(n 是一个偶数)。Alice 非常喜欢这些糖,她想要在遵循医生建议的情况下,尽可能吃到最多不同种类的糖。

给你一个长度为 n 的整数数组 candyType ,返回: Alice 在仅吃掉 n / 2 枚糖的情况下,可以吃到糖的最多种类数。

 

示例 1:

输入:candyType = [1,1,2,2,3,3] 输出:3 解释:Alice 只能吃 6 / 2 = 3 枚糖,由于只有 3 种糖,她可以每种吃一枚。

/**
 * @param {number[]} candyType
 * @return {number}
 */
var distributeCandies = function(candyType) {
    const candyTypeNumber = new Set(candyType).size
    const candyTypeTolNumber = candyType.length/2
    return candyTypeNumber>candyTypeTolNumber?candyTypeTolNumber:candyTypeNumber

};

生活不可以逆来顺受,唯有直面惨淡的人生,本就生活不易,为何拘泥于别人的眼光

给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

 

示例 1:

输入: nums = [1,2,3,4,5,6,7], k = 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,7,1,2,3,4]

var rotate = function(nums, k) {
    if(k>=nums.length){
        const middel = k%nums.length
        if(middel===0){
            return nums
        }else{
            const a =   nums.splice(nums.length-middel,middel)
            const qrray = nums.unshift(...a)
            return nums
        }
    }else{
        const a =   nums.splice(nums.length-k,k)
        const qrray = nums.unshift(...a)
        return nums
    }

};

当你心态不好时请转变你的思维方式,总有一种方式适合你

最长回文子串

难度中等4432

给你一个字符串 s,找到 s 中最长的回文子串。

 

示例 1:

输入: s = "babad"
输出: "bab"
解释: "aba" 同样是符合题意的答案。
/**
 * @param {string} s
 * @return {string}
 */
var longestPalindrome = function longestPalindrome(s) {
    let res = '';
    //循环来进行中间文字的获取(就是扩散的中心点,向两端扩散)
   for(let i=0;i<s.length;i++){
       const res1 = strString12(s,i,i);
       const res2 = strString12(s,i,i+1)
       res = res1.length > res.length ? res1:res;
       res = res2.length > res.length ? res2:res
   }
   return res
};
function strString12(s,l,r){
    //从字符串的中间向两遍扩散来查找符合要求的数据
    while(l>=0&&r<s.length && s[l]===s[r]){
        l--;
        r++
    }
    return s.substr(l + 1, r - l - 1)
}
  1. 边界着色DFS(深度优先搜索) 题目内容写的和屎一样。。。。。

难度中等113收藏分享切换为英文接收动态反馈

给你一个大小为 m x n 的整数矩阵 grid ,表示一个网格。另给你三个整数 rowcol 和 color 。网格中的每个值表示该位置处的网格块的颜色。

两个网格块属于同一 连通分量 需满足下述全部条件:

  • 两个网格块颜色相同
  • 在上、下、左、右任意一个方向上相邻

连通分量的边界 ****是指连通分量中满足下述条件之一的所有网格块:

  • 在上、下、左、右四个方向上与不属于同一连通分量的网格块相邻
  • 在网格的边界上(第一行/列或最后一行/列)

请你使用指定颜色 color 为所有包含网格块 grid[row][col] 的 连通分量的边界 进行着色,并返回最终的网格 grid 。

 

示例 1:

输入: grid = [[1,1],[1,2]], row = 0, col = 0, color = 3
输出: [[3,3],[3,2]]
const colorBorder = (grid, row, col, color) => {
    //m时矩阵的行 n是矩阵的列
    const [m, n] = [grid.length, grid[0].length];
    //起始点,也可以说是站位点
    const oldColor = grid[row][col];
    const visit = new Set();
    //主要的意义在于 就是能够使用递归的方式,由点向面扩展开来能够进行使用。四面八方扩散,(层层递进,能够层层使用)。
    const dfs = (i, j) => {
        debugger
        console.log(i,j)
        //不在矩阵中
        if (i < 0 || i >= m || j < 0 || j >= n) return true;
        //下交角点 与 原起点 高度中线相对应
        const index = i * n + j;
        //如果在visit中就是回到了原来查找的方格上所以就不需要查找了
        if (visit.has(index)) return false;
        //为什么会不相等(因为原有的方框被颜色了)
        if (grid[i][j] !== oldColor) return true;
        
        //坐标值挡在set对象中
        visit.add(index);
        let flag = false;
        //下
        if (dfs(i + 1, j)) flag = true;
        //右
        if (dfs(i, j + 1)) flag = true;
        //上
        if (dfs(i - 1, j)) flag = true;
        //左
        if (dfs(i, j - 1)) flag = true;
        if (flag) grid[i][j] = color;
        return false;
    };
    dfs(row, col);
    console.log(visit)
    console.log(grid)
    return grid;
};
作者:lzxjack
链接:https://leetcode-cn.com/problems/coloring-a-border/solution/dfs-javascript-by-lzxjack-yi2i/

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。 X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。  C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。 给你一个整数,将其转为罗马数字。

 

示例 1:

输入: num = 3 输出: "III"

var intToRoman = function(num) {
    let nums=[1000,900,500,400,100,90,50,40,10,9,5,4,1],
        chars=['M','CM','D','CD','C','XC','L','XL','X','IX','V','IV','I'];
    let result='';
    while(num){
        if(num>=nums[0]){
            result+=chars[0];
            num-=nums[0];
        }else{
            nums.shift();
            chars.shift();
        }
    }
    return result;
};

部分题目来源:力扣

解题思路:部分本人原创,如果借鉴表明出处(借鉴是否抄袭无考究、如有问题及时联系本人删除或者更更正)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。