每日一道算法题(10.21~11.19)

270 阅读11分钟
  • 题目来自力扣
  • 文章只记录个人解题思路,并非最优
  • 每周一至周五每日一题,周末不更新

1.合并两个有序数组

给定两个有序整数数组nums1 和 nums2,将 nums2 合并到nums1中,使得num1 成为一个有序数组。

说明:
  • 初始化nums1 和 nums2 的元素数量分别为m 和 n。
  • 你可以假设nums1有足够的空间(空间大小大于或等于m + n)来保存 nums2 中的元素。
示例:
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6],       n = 3

输出: [1,2,2,3,5,6]

链接:leetcode-cn.com/problems/me…

解题

数组拼接后sort排序

var merge = function(nums1, m, nums2, n) {
    Object.assign(nums1, [...nums1.slice(0, m), ...nums2.slice(0, n)].sort((a, b) => a - b))
};

2.杨辉三角 II

给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行。
在杨辉三角中,每个数是它左上方和右上方的数的和。

示例:
输入: 3
输出: [1,3,3,1]

链接:leetcode-cn.com/problems/pa…

解题

动态的更新每层元素,直到更新至最终的结果层

var getRow = function(rowIndex) {
    let res = [];
    for(let i = 1; i <= rowIndex; i++){
        res.push(1);
        for(let j = i - 1; j > 0; j--){
            res[j] += res[j-1];
        }
    }
    res.push(1);
    return res;
};

3.存在重复元素

给定一个整数数组,判断是否存在重复元素。
如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。

示例:
输入: [1,2,3,1]
输出: true

输入: [1,2,3,4]
输出: false

链接:leetcode-cn.com/problems/co…

解题

1.set 去重之后对比长度

var containsDuplicate = function(nums) {
    return (new Set(nums).size !== nums.length)
};
  1. 循环对比有没有相同值
var containsDuplicate = function(nums) {
    for (let i = 0; i < nums.length; i++) {
        for (let j = i + 1; j < nums.length; j++) {
            if (nums[i] === nums[j]) {
                return true
            }
        }
    }
    return false
};

83. 删除排序链表中的重复元素

给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。

示例:
输入: 1->1->2
输出: 1->2

链接:leetcode-cn.com/problems/re…

解题

循环,判断当前值是否等于下一个值,如果是就跳过下一个

var deleteDuplicates = function(head) {
    var cur = head;
    while(cur && cur.next) {
        if(cur.val == cur.next.val) {
            cur.next = cur.next.next;
        } else {
            cur = cur.next;
        }
    }
    return head;
};

141. 环形链表

给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

示例:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

链接:leetcode-cn.com/problems/li…

解题

利用JSON.stringify()不能含有循环引用的结构。

var hasCycle = function(head) {
    try{
        JSON.stringify(head);
        return false;
    }
    catch(err){
        return true;
    }
};

160. 相交链表

编写一个程序,找到两个单链表相交的起始节点。

示例:
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

链接:leetcode-cn.com/problems/in…

解题

初始化两个指针,遍历A+B跟B+A

var getIntersectionNode = function(headA, headB) {
    var pA = headA;
    var pB = headB;
    while(pA !== pB){
        pB = pB ? pB.next : headA;
        pA = pA ? pA.next : headB;
    }
    return pA;
};

203. 移除链表元素

删除链表中等于给定值 val 的所有节点。

示例:
输入: 1->2->6->3->4->5->6, val = 6
输出: 1->2->3->4->5

链接:leetcode-cn.com/problems/re…

解题

创建虚拟头,然后循环,如果有相同的就移除

var removeElements = function(head, val) {
    let node = {next: head}
    var cur = node;
    while(cur.next) {
        if(cur.next.val === val) {
            cur.next = cur.next.next;
        } else {
            cur = cur.next;
        }
    }
    return node.next;
};

206. 反转链表

反转一个单链表。

示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

链接:leetcode-cn.com/problems/re…

解题
var reverseList = function(head) {
    let pre = null;
    let cur = head;
    while(cur) {
        let nextTemp = cur.next;
        cur.next = pre;
        pre = cur;
        cur = nextTemp;
    }
    return pre;
};

202. 快乐数

编写一个算法来判断一个数是不是“快乐数”。
一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。

示例:
输入: 19
输出: true
解释: 
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1

链接:leetcode-cn.com/problems/ha…

解题

定义一个set集合,如果出现重复值就返回false,如果没有就一直相加,直到为1

var isHappy = function(n) {
    let set = new Set(), sum
    n += ''
    while (sum !== 1) {
        sum = 0
        for (let i = 0; i < n.length; i++) {
            sum += n[i]*n[i]
        }
        n = sum + ''
        if (set.has(sum)) return false
        set.add(sum)
    }
  return true
};

204. 计数质数

统计所有小于非负整数 n 的质数的数量。

示例:
输入: 10
输出: 4
解释: 小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。

链接:leetcode-cn.com/problems/co…

解题
  1. 遍历,如果不是质数就减一,但是超时
var countPrimes = function(n) {
    if (n < 2) return 0
    let count = n - 2
    for (let i = 2; i < n; i++) {
        for (j = 2; j < i; j ++) {
            if (i%j === 0) {
                count -= 1
                break
            }
        }
    }
    return count
};

  1. 首先,将2到n范围内的所有整数写下来。其中最小的数字2是素数。将表中所有2的倍数都划去。表中剩余的最小数字是3,它不能被更小的数整除,所以是素数。再将表中所有3的倍数全都划去。依次类推,最后剩下的就是质数
var countPrimes = function (n) {
    if (n <= 2) {
        return 0
    }
    // 生成一个0-n-1的数组
    let temp = [...new Array(n).keys()];
    temp[0] = temp[1] = null
    for (let i = 2; i < n; i++) {
        for (let j = i; i * j <= n; j++) {
            temp[i * j] = null;
        }
    }
    temp = temp.filter(function (a) {
        return a != null
    })
    return temp.length
}; 

205. 同构字符串

给定两个字符串 s 和 t,判断它们是否是同构的。
如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。
所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。

示例:
输入: s = "egg", t = "add"
输出: true

输入: s = "foo", t = "bar"
输出: false

链接:leetcode-cn.com/problems/is…

解题

判断每个字符出现的位置是否相同

var isIsomorphic = function(s, t) {
    for (let i = 0; i < s.length; i++) {
        if (s.indexOf(s[i]) !== t.indexOf(t[i])) {
            return false
        }
    }
    return true
};

219. 存在重复元素 II

给定一个整数数组和一个整数k,判断数组中是否存在两个不同的索引i和j,使得nums [i] = nums [j],并且 i 和 j的差的绝对值最大为 k。

示例:
输入: nums = [1,2,3,1], k = 3
输出: true

输入: nums = [1,2,3,1,2,3], k = 2
输出: false

链接:leetcode-cn.com/problems/co…

解题

利用map记录索引

var containsNearbyDuplicate = function (nums, k) {
    const map = new Map();
    for (let i = 0; i < nums.length; i++) {
        if (map.has(nums[i]) && i - map.get(nums[i]) <= k) {
            return true;
        } else {
            map.set(nums[i], i);
        }
    }
    return false;
};

242. 有效的字母异位词

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

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

输入: s = "rat", t = "car"
输出: false

链接:leetcode-cn.com/problems/va…

解题

排序,再比较是否相同

var isAnagram = function(s, t) {
    if (s.length !== t.length) return false
    return s.split('').sort().join('') === t.split('').sort().join('')
};

844. 比较含退格的字符串

给定 S 和 T 两个字符串,当它们分别被输入到空白的文本编辑器后,判断二者是否相等,并返回结果。 # 代表退格字符。

示例:
输入:S = "ab#c", T = "ad#c"
输出:true
解释:S 和 T 都会变成 “ac”。

输入:S = "a#c", T = "b"
输出:false
解释:S 会变成 “c”,但 T 仍然是 “b”。

链接:leetcode-cn.com/problems/ba…

解题

创建一个新数组,将输入数组的元素push进去,如果遇到’#‘就pop()

var backspaceCompare = function(S, T) {
    S = S.split('')
    T = T.split('')
    return fun(S) === fun(T)
};

function fun(arr) {
    let res = []
    for(let i = 0; i < arr.length; i++){
        if(arr[i] === '#') {
            res.pop()
        } else {
            res.push(arr[i])
        }
    }
    return res.join('')
}

1047. 删除字符串中的所有相邻重复项

给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例:
输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"

链接:leetcode-cn.com/problems/re…

解题

创建一个新数组,将元素组元素push(),如果遇到相同的就pop()

var removeDuplicates = function(S) {
    let arr = S.split('')
    let res = []
    for (let i = 0; i < arr.length; i++) {
        if (arr.length && arr[i] === res[res.length - 1]) {
            res.pop()
            continue
        }
        res.push(arr[i])
    }
    return res.join('')
};

1249. 移除无效的括号

给你一个由 '('、')' 和小写字母组成的字符串 s。

你需要从字符串中删除最少数目的 '(' 或者 ')' (可以删除任意位置的括号),使得剩下的「括号字符串」有效。

请返回任意一个合法字符串。

有效「括号字符串」应当符合以下 任意一条 要求:

  • 空字符串或只包含小写字母的字符串
  • 可以被写作 AB(A 连接 B)的字符串,其中 A 和 B 都是有效「括号字符串」
  • 可以被写作 (A) 的字符串,其中 A 是一个有效的「括号字符串」
示例:
输入:s = "lee(t(c)o)de)"
输出:"lee(t(c)o)de"
解释:"lee(t(co)de)" , "lee(t(c)ode)" 也是一个可行答案。

输入:s = "a)b(c)d"
输出:"ab(c)d"

链接:leetcode-cn.com/problems/mi…

解题

从左至右删掉无效')',从右至左删除无效'('

var minRemoveToMakeValid = function(s) {
    let res = ''
    let stack = []
    let rep = ''
    for (let i = 0; i < s.length; i++) {
        if (s[i] === ')') {
            if (stack.length) {
                stack.pop()
                res += (s[i])
            }
        } else {
            if (s[i] === '(') {
                stack.push(s[i])
            }
            res += (s[i])
        }
    }
    stack = []
    for (let i = res.length - 1; i >= 0; i--) {
        if (res[i] === '(') {
            if (stack.length) {
                stack.pop()
                rep = res[i] + rep
            }
        } else {
            if (res[i] === ')') {
                stack.push(res[i])
            }
            rep = res[i] + rep
        }
    }
    return rep
};

1209. 删除字符串中的所有相邻重复项 II

给你一个字符串 s,「k 倍重复项删除操作」将会从s 中选择 k 个相邻且相等的字母,并删除它们,使被删去的字符串的左侧和右侧连在一起。

你需要对 s 重复进行无限次这样的删除操作,直到无法继续为止。

在执行完所有删除操作后,返回最终得到的字符串。

本题答案保证唯一。

示例:
输入:s = "abcd", k = 2
输出:"abcd"
解释:没有要删除的内容。

输入:s = "deeedbbcccbdaa", k = 3
输出:"aa"
解释: 
先删除 "eee""ccc",得到 "ddbbbdaa"
再删除 "bbb",得到 "dddaa"
最后删除 "ddd",得到 "aa"

链接:leetcode-cn.com/problems/re…

解题

截取最后k个值,判断是不是所有值都相等,相同就删掉

var removeDuplicates = function(s, k) {
    let res = []
    for (let i = 0; i < s.length; i++) {
        if (res.length < k - 1) {
            res.push(s[i])
        } else {
            let t = res.slice(-(k-1))
            if (t.every(e => e === s[i])) {
                res.splice(-(k-1))
            } else {
                res.push(s[i])
            }
        }
    }
    return res.join('')
};

1209. 删除字符串中的所有相邻重复项 II

给出一个字符串 s(仅含有小写英文字母和括号)。

请你按照从括号内到外的顺序,逐层反转每对匹配括号中的字符串,并返回最终的结果。

注意,您的结果中 不应 包含任何括号。

示例:
输入:s = "(abcd)"
输出:"dcba"

输入:s = "(u(love)i)"
输出:"iloveu"

链接:leetcode-cn.com/problems/re…

解题
var reverseParentheses = function(s) {
    let stack=[];
    let tempstack=[];
    for(let i = 0; i < s.length; ++i) {
        if(s[i]!=")") stack.push(s[i]);
        else {
            while(stack[stack.length-1]!="("){
                tempstack.push(stack.pop());
            }
            stack.pop();
            while(tempstack.length>0){
                stack.push(tempstack.shift());
            }
        }
    }
    return stack.join("");
};

922. 按奇偶排序数组 II

给定一个非负整数数组 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] 也会被接受。

链接:leetcode-cn.com/problems/so…

解题

奇数位跟偶数位分别赋值

var sortArrayByParityII = function(A) {
    let res = []
    let odd = 1
    let even = 0
    for (let i = 0; i < A.length; i++) {
        if (A[i] % 2 === 0) {
            res[even] = A[i]
            even += 2
        } else if (A[i] % 2 === 1) {
            res[odd] = A[i]
            odd += 2
        } else {
        }
    }
    return res
};

976. 三角形的最大周长

给定由一些正数(代表长度)组成的数组 A,返回由其中三个长度组成的、面积不为零的三角形的最大周长。

如果不能形成任何面积不为零的三角形,返回 0。

示例:
输入:[2,1,2]
输出:5

输入:[1,2,1]
输出:0

链接:leetcode-cn.com/problems/la…

解题

排序,找最大的能组成三角形的值

var largestPerimeter = function(A) {
    A.sort((a, b) => a - b)
    for (let i = A.length - 3; i > -1; i --) {
        if (A[i] + A[i+1] > A[i+2]) {
            return A[i] + A[i+1] + A[i+2]
        }
    }
    return 0
};