LeetCode 算法题系列(第一周 25道)(下)

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

双指针


const validMountainArray = (A) => {
    const n = A.length;
    let i = 0;
    let j = n - 1;
    while (i + 1 < n && A[i] < A[i + 1]) {
        i++;
    }
    while (j - 1 >= 0 && A[j - 1] > A[j]) {
        j--;
    }
    if (i != 0 && i == j && j != n - 1) {
        return true;
    }
    return false;
};


167. 两数之和 II - 输入有序数组



给定一个已按照 非递减顺序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。


函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。

你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。


示例 1

输入:numbers = [2,7,11,15], target = 9

输出:[1,2]

解释:27 之和等于目标数 9 。因此 index1 = 1, index2 = 2


示例 2

输入:numbers = [2,3,4], target = 6

输出:[1,3]


示例 3

输入:numbers = [-1,0], target = -1

输出:[1,2]


提示:


   2 <= numbers.length <= 3 * 104

   -1000 <= numbers[i] <= 1000

   numbers 按 非递减顺序 排列

   -1000 <= target <= 1000

   仅存在一个有效答案


双指针


var twoSum = function (numbers, target) {
    let i = 0, j = numbers.length-1;
    while (i <= j) {
        if (numbers[i] + numbers[j] > target) {
            j--
        } else if (numbers[i] + numbers[j] === target) {
            return [++i, ++j]
        } else {
            i++
        }
    }
};


1984. 学生分数的最小差值



给你一个 下标从 0 开始 的整数数组 nums ,其中 nums[i] 表示第 i 名学生的分数。另给你一个整数 k 。


从数组中选出任意 k 名学生的分数,使这 k 个分数间 最高分 和 最低分 的 差值 达到 最小化 。


返回可能的 最小差值 。


示例 1:


输入:nums = [90], k = 1

输出:0

解释:选出 1 名学生的分数,仅有 1 种方法:

- [90] 最高分和最低分之间的差值是 90 - 90 = 0

可能的最小差值是 0


示例 2:

输入:nums = [9,4,1,7], k = 2

输出:2

解释:选出 2 名学生的分数,有 6 种方法:

- [9,4,1,7] 最高分和最低分之间的差值是 9 - 4 = 5

- [9,4,1,7] 最高分和最低分之间的差值是 9 - 1 = 8

- [9,4,1,7] 最高分和最低分之间的差值是 9 - 7 = 2

- [9,4,1,7] 最高分和最低分之间的差值是 4 - 1 = 3

- [9,4,1,7] 最高分和最低分之间的差值是 7 - 4 = 3

- [9,4,1,7] 最高分和最低分之间的差值是 7 - 1 = 6

可能的最小差值是 2


提示:

 

1 <= k <= nums.length <= 1000
    0 <= nums[i] <= 1
var minimumDifference = function (nums, k) {
    nums = nums.sort((a, b) => a - b)
    let ret = Infinity
    for (let i = 0; i + k - 1 < nums.length; i++) {
        if (nums[i + k - 1] - nums[i] < ret) {
            ret = nums[i + k - 1] - nums[i];
        }
    }
    return ret
};


1436. 旅行终点站



给你一份旅游线路图,该线路图中的旅行线路用数组 paths 表示,其中 paths[i] = [cityAi, cityBi] 表示该线路将会从 cityAi 直接前往 cityBi 。请你找出这次旅行的终点站,即没有任何可以通往其他城市的线路的城市。


题目数据保证线路图会形成一条不存在循环的线路,因此恰有一个旅行终点站。


示例 1

输入:paths = [["London","New York"],["New York","Lima"],["Lima","Sao Paulo"]]

输出:"Sao Paulo"

解释:从 "London" 出发,最后抵达终点站 "Sao Paulo" 。本次旅行的路线是 "London" -> "New York" -> "Lima" -> "Sao Paulo"


示例 2

输入:paths = [["B","C"],["D","B"],["C","A"]]

输出:"A"

解释:所有可能的线路是:

"D" -> "B" -> "C" -> "A".

"B" -> "C" -> "A".

"C" -> "A".

"A".

显然,旅行终点站是 "A"


示例 3

输入:paths = [["A","Z"]]

输出:"Z"


提示:

 

1 <= paths.length <= 100
    paths[i].length == 2
    1 <= cityAi.length, cityBi.length <= 10
    cityAi != cityBi


   所有字符串均由大小写英文字母和空格字符组成。


Set


var destCity = function(paths) {
    let ans = new Set()
    for(let i of paths){
        ans.add(i[0])
    }
    for(let j  of paths){
        if(!ans.has(j[1])){
            return j[1]
        }
    }
    return ''
};


876. 链表的中间结点



给定一个头结点为 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.


示例 2

输入:[1,2,3,4,5,6]

输出:此列表中的结点 4 (序列化形式:[4,5,6])

由于该列表有两个中间结点,值分别为 34,我们返回第二个结点。


提示:

   给定链表的结点数介于 1100 之间。

var middleNode = function(head) {
    let slow = head,fast = head;
    while(fast!==null && fast.next!==null){
        slow = slow.next;
        fast = fast.next.next;
    }
    return slow
};


374. 猜数字大小



374. 猜数字大小


猜数字游戏的规则如下:

每轮游戏,我都会从 1n 随机选择一个数字。 请你猜选出的是哪个数字。

如果你猜错了,我会告诉你,你猜测的数字比我选出的数字是大了还是小了。


你可以通过调用一个预先定义好的接口 int guess(int num) 来获取猜测结果,返回值一共有 3 种可能的情况(-1,1 或 0):

-1:我选出的数字比你猜的数字小 pick < num

1:我选出的数字比你猜的数字大 pick > num

0:我选出的数字和你猜的数字一样。恭喜!你猜对了!pick == num

返回我选出的数字。


示例 1

输入:n = 10, pick = 6

输出:6


示例 2

输入:n = 1, pick = 1

输出:1


示例 3

输入:n = 2, pick = 1

输出:1


示例 4

输入:n = 2, pick = 2

输出:2


提示:

1 <= n <= 231 - 1
    1 <= pick <= n


二分法


var guessNumber = function (n) {
    let left = 1, right = n
    while (left < right) {
        const mid = Math.floor((right - left) / 2 + left)
        if (guess(mid) <= 0) {
            right = mid
        } else {
            left = mid + 1
        }
    }
    return left
};


405. 数字转换为十六进制数



405. 数字转换为十六进制数


给定一个整数,编写一个算法将这个数转换为十六进制数。对于负整数,我们通常使用 补码运算 方法。


注意:

十六进制中所有字母(a-f)都必须是小写。

十六进制字符串中不能包含多余的前导零。如果要转化的数为0,那么以单个字符'0'来表示;对于其他情况,十六进制字符串中的第一个字符将不会是0字符。

给定的数确保在32位有符号整数范围内。


不能使用任何由库提供的将数字直接转换或格式化为十六进制的方法。


示例 1:

输入:

26


输出:

"1a"


示例 2:

输入:

-1


输出:

"ffffffff"
var toHex = function (num) {
    const hex = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f']
    if (num === 0) {
        return '0'
    }
    let ans = "";
    if (num < 0) {
        num = Math.pow(2, 32) - Math.abs(num);
    }
    while (num) {
        ans += hex[num % 16];
        num = Math.floor(num / 16);
    }
    return ans.split("").reverse().join("");
};


643. 子数组最大平均数 I



给你一个由 n 个元素组成的整数数组 nums 和一个整数 k 。请你找出平均数最大且 长度为 k 的连续子数组,并输出该最大平均数。


任何误差小于 10-5 的答案都将被视为正确答案。


示例 1:


输入:nums = [1,12,-5,-6,50,3], k = 4

输出:12.75

解释:最大平均数 (12-5-6+50)/4 = 51/4 = 12.75


示例 2:


输入:nums = [5], k = 1

输出:5.00000


提示:


n == nums.length
    1 <= k <= n <= 105
    -104 <= nums[i] <= 104
var findMaxAverage = function (nums, k) {
    let max = ans = [...nums].slice(0, k).reduce((acc, prev) => acc += prev);
    for (let i = 1; i <= nums.length - k; i++) {
        ans = ans - nums[i - 1] + nums[i + k - 1]
        max = Math.max(ans, max)
    }
    return max / k
};


283. 移动零



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


示例:

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

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


说明:

   必须在原数组上操作,不能拷贝额外的数组。

   尽量减少操作次数。


var moveZeroes = function (nums) {
    let i = 0, j = 0;
    while (i < nums.length) {
        if (nums[i] != 0) {
            nums[j++] = nums[i]
        }
        i++
    }
    for (let a = j; a < nums.length; a++) {
        nums[a] = 0
    }
    return nums
};
相关文章
|
2月前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
43 0
|
1月前
|
存储 算法 Java
leetcode算法题-有效的括号(简单)
【11月更文挑战第5天】本文介绍了 LeetCode 上“有效的括号”这道题的解法。题目要求判断一个只包含括号字符的字符串是否有效。有效字符串需满足左括号必须用相同类型的右括号闭合,并且左括号必须以正确的顺序闭合。解题思路是使用栈数据结构,遍历字符串时将左括号压入栈中,遇到右括号时检查栈顶元素是否匹配。最后根据栈是否为空来判断字符串中的括号是否有效。示例代码包括 Python 和 Java 版本。
|
2月前
|
算法
每日一道算法题(Leetcode 20)
每日一道算法题(Leetcode 20)
29 2
|
4月前
|
算法
测试工程师的技能升级:LeetCode算法挑战与职业成长
这篇文章通过作者亲身体验LeetCode算法题的过程,探讨了测试工程师学习算法的重要性,并强调了算法技能对于测试职业成长的必要性。
80 1
测试工程师的技能升级:LeetCode算法挑战与职业成长
|
4月前
|
算法 Java
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
57 6
|
4月前
|
存储 算法 Java
LeetCode经典算法题:打家劫舍java详解
LeetCode经典算法题:打家劫舍java详解
72 2
|
4月前
|
人工智能 算法 Java
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
54 1
|
4月前
|
存储 算法 Java
LeetCode经典算法题:预测赢家+香槟塔java解法
LeetCode经典算法题:预测赢家+香槟塔java解法
64 1
|
4月前
|
存储 算法 Java
LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解
LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解
83 0
|
4月前
|
算法 Java
LeetCode初级算法题:子数组最大平均数+二叉树的最小深度+最长连续递增序列+柠檬水找零
LeetCode初级算法题:子数组最大平均数+二叉树的最小深度+最长连续递增序列+柠檬水找零
44 0