前端面试题之算法

142 阅读11分钟

字符串有效性

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。

思路: 第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false 第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false 第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false

var isValid = function(s) {
    const n = s.length;
    if (n % 2 === 1) {
        return false;
    }
    const pairs = new Map([
        [')', '('],
        [']', '['],
        ['}', '{']
    ]);
    const stk = [];
    for (let ch of s){
        if (pairs.has(ch)) {
            if (!stk.length || stk[stk.length - 1] !== pairs.get(ch)) {
                return false;
            }
            stk.pop();
        } 
        else {
            stk.push(ch);
        }
    };
    return !stk.length;
};

翻转二叉树/二叉树镜像

截图.png

思路:我们从根节点开始,递归地对树进行遍历,并从叶子节点先开始翻转。如果当前遍历到的节点 \textit{root}root 的左右两棵子树都已经翻转,那么我们只需要交换两棵子树的位置,即可完成以 \textit{root}root 为根节点的整棵子树的翻转。

var invertTree = function(root) { if (root === null) { return null; } const left = invertTree(root.left); const right = invertTree(root.right); root.left = right; root.right = left; return root; };

比较版本号

方法一:字符串分割

我们可以将版本号按照点号分割成修订号,然后从左到右比较两个版本号的相同下标的修订号。在比较修订号时,需要将字符串转换成整数进行比较。注意根据题目要求,如果版本号不存在某个下标处的修订号,则该修订号视为 00。

var compareVersion = function(version1, version2) {
	const v1 = version1.split('.');
	const v2 = version2.split('.');
	for (let i = 0; i < v1.length || i < v2.length; ++i) {
		let x = 0,
			y = 0;
		if (i < v1.length) {
			x = parseInt(v1[i]);
		}
		if (i < v2.length) {
			y = parseInt(v2[i]);
		}
		if (x > y) {
			return 1;
		}
		if (x < y) {
			return -1;
		}
	}
	return 0;
};

时间复杂度:O(n+m)(或 O(n,m),这是等价的),其中 nn 是字符串version1 的长度,mm 是字符串version2 的长度。

空间复杂度:O(n+m),我们需要 O(n+m) 的空间存储分割后的修订号列表。

方法二:双指针

方法一需要存储分割后的修订号,为了优化空间复杂度,我们可以在分割版本号的同时解析出修订号进行比较。

var compareVersion = function(version1, version2) {
    const n = version1.length, m = version2.length;
    let i = 0, j = 0;
    while (i < n || j < m) {
        let x = 0;
        for (; i < n && version1[i] !== '.'; ++i) {
            x = x * 10 + version1[i].charCodeAt() - '0'.charCodeAt();
        }
        ++i; // 跳过点号
        let y = 0;
        for (; j < m && version2.charAt(j) !== '.'; ++j) {
            y = y * 10 + version2[j].charCodeAt() - '0'.charCodeAt();
        }
        ++j; // 跳过点号
        if (x !== y) {
            return x > y ? 1 : -1;
        }
    }
    return 0;
};

复杂度分析

时间复杂度:O(n+m),其中 nn 是字符串version1的长度,mm 是字符串 version2 的长度。

空间复杂度:O(1),我们只需要常数的空间保存若干变量。

二进制矩阵中的所有元素不是 0 就是 1 。

四叉树交集

给你两个四叉树,quadTree1 和 quadTree2。其中 quadTree1 表示一个 n * n 二进制矩阵,而 quadTree2 表示另一个 n * n 二进制矩阵。

请你返回一个表示 n * n 二进制矩阵的四叉树,它是 quadTree1 和 quadTree2 所表示的两个二进制矩阵进行 按位逻辑或运算 的结果。

注意,当 isLeaf 为 False 时,你可以把 True 或者 False 赋值给节点,两种值都会被判题机制 接受 。

四叉树数据结构中,每个内部节点只有四个子节点。此外,每个节点都有两个属性:

val:储存叶子结点所代表的区域的值。1 对应 True,0 对应 False; isLeaf: 当这个节点是一个叶子结点时为 True,如果它有 4 个子节点则为 False 。

class Node {
    public boolean val;
    public boolean isLeaf;
    public Node topLeft;
    public Node topRight;
    public Node bottomLeft;
    public Node bottomRight;
}

我们可以按以下步骤为二维区域构建四叉树:

如果当前网格的值相同(即,全为 0 或者全为 1),将 isLeaf 设为 True ,将 val 设为网格相应的值,并将四个子节点都设为 Null 然后停止。 如果当前网格的值不同,将 isLeaf 设为 False, 将 val 设为任意值,然后如下图所示,将当前网格划分为四个子网格。 使用适当的子网格递归每个子节点。

如果你想了解更多关于四叉树的内容,可以参考 wiki 。

四叉树格式:

输出为使用层序遍历后四叉树的序列化形式,其中 null 表示路径终止符,其下面不存在节点。

它与二叉树的序列化非常相似。唯一的区别是节点以列表形式表示 [isLeaf, val] 。

如果 isLeaf 或者 val 的值为 True ,则表示它在列表 [isLeaf, val] 中的值为 1 ;如果 isLeaf 或者 val 的值为 False ,则表示值为 0 。

 

示例 1:

输入:
quadTree1 = [[0,1],[1,1],[1,1],[1,0],[1,0]]
quadTree2 = [[0,1],[1,1],[0,1],[1,1],[1,0],null,null,null,null,[1,0],[1,0],[1,1],[1,1]]
输出:[[0,0],[1,1],[1,1],[1,1],[1,0]]
解释:quadTree1 和 quadTree2 如上所示。由四叉树所表示的二进制矩阵也已经给出。
如果我们对这两个矩阵进行按位逻辑或运算,则可以得到下面的二进制矩阵,由一个作为结果的四叉树表示。

注意,我们展示的二进制矩阵仅仅是为了更好地说明题意,你无需构造二进制矩阵来获得结果四叉树。

示例 2:

输入:
quadTree1 = [[1,0]],
quadTree2 = [[1,0]]
输出:[[1,0]]
解释:两个数所表示的矩阵大小都为 1*1,值全为 0 
结果矩阵大小为 1*1,值全为 0

示例 3:

输入:
quadTree1 = [[0,0],[1,0],[1,0],[1,1],[1,1]],
quadTree2 = [[0,0],[1,1],[1,1],[1,0],[1,1]]
输出:[[1,1]]

示例 4:

输入:quadTree1 = [[0,0],[1,1],[1,0],[1,1],[1,1]]
, quadTree2 = [[0,0],[1,1],[0,1],[1,1],[1,1],null,null,null,null,[1,1],[1,0],[1,0],[1,1]]
输出:[[0,0],[1,1],[0,1],[1,1],[1,1],null,null,null,null,[1,1],[1,0],[1,0],[1,1]]

示例 5:

输入:quadTree1 = [[0,1],[1,0],[0,1],[1,1],[1,0],null,null,null,null,[1,0],[1,0],[1,1],[1,1]]
, quadTree2 = [[0,1],[0,1],[1,0],[1,1],[1,0],[1,0],[1,0],[1,1],[1,1]]
输出:[[0,0],[0,1],[0,1],[1,1],[1,0],[1,0],[1,0],[1,1],[1,1],[1,0],[1,0],[1,1],[1,1]]
function Node(val,isLeaf,topLeft,topRight,bottomLeft,bottomRight) {
     this.val = val;
     this.isLeaf = isLeaf;
     this.topLeft = topLeft;
     this.topRight = topRight;
     this.bottomLeft = bottomLeft;
     this.bottomRight = bottomRight;
};

/**
 * @param {Node} quadTree1
 * @param {Node} quadTree2
 * @return {Node}
 */
var intersect = function(quadTree1, quadTree2) {
    
    if (quadTree1.isLeaf) {
        if (quadTree1.val) {
            return new Node(true, true)
        }
        return new Node(quadTree2.val, quadTree2.isLeaf, quadTree2.topLeft, quadTree2.topRight, quadTree2.bottomLeft, quadTree2.bottomRight)
    }
    if (quadTree2.isLeaf) {
        return intersect(quadTree2, quadTree1)
    }
    const o1 = intersect(quadTree1.topLeft, quadTree2.topLeft)
    const o2 = intersect(quadTree1.topRight, quadTree2.topRight)
    const o3 = intersect(quadTree1.bottomLeft, quadTree2.bottomLeft)
    const o4 = intersect(quadTree1.bottomRight, quadTree2.bottomRight)

    if (o1.isLeaf && o2.isLeaf && o3.isLeaf && o4.isLeaf && o1.val === o2.val && o1.val === o3.val && o1.val === o4.val) {
        return new Node(o1.val, true)
    }
    return new Node(false, false, o1, o2, o3, o4)
};
 
 

隔离病毒

病毒扩散得很快,现在你的任务是尽可能地通过安装防火墙来隔离病毒。

假设世界由 m x n 的二维矩阵 isInfected 组成, isInfected[i][j] == 0 表示该区域未感染病毒,而  isInfected[i][j] == 1 表示该区域已感染病毒。可以在任意 2 个相邻单元之间的共享边界上安装一个防火墙(并且只有一个防火墙)。

每天晚上,病毒会从被感染区域向相邻未感染区域扩散,除非被防火墙隔离。现由于资源有限,每天你只能安装一系列防火墙来隔离其中一个被病毒感染的区域(一个区域或连续的一片区域),且该感染区域对未感染区域的威胁最大且 保证唯一 。

你需要努力使得最后有部分区域不被病毒感染,如果可以成功,那么返回需要使用的防火墙个数; 如果无法实现,则返回在世界被病毒全部感染时已安装的防火墙个数。

const dirs = [[-1, 0], [1, 0], [0, -1], [0, 1]];
var containVirus = function(isInfected) {
    const m = isInfected.length, n = isInfected[0].length;
    let ans = 0;
    while (true) {
        const neighbors = [];
        const firewalls = [];
        for (let i = 0; i < m; ++i) {
            for (let j = 0; j < n; ++j) {
                if (isInfected[i][j] === 1) {
                    const queue = [];
                    queue.push([i, j]);
                    const neighbor = new Set();
                    let firewall = 0, idx = neighbors.length + 1;
                    isInfected[i][j] = -idx;

                    while (queue.length > 0) {
                        const arr = queue.shift();
                        let x = arr[0], y = arr[1];
                        for (let d = 0; d < 4; ++d) {
                            let nx = x + dirs[d][0], ny = y + dirs[d][1];
                            if (nx >= 0 && nx < m && ny >= 0 && ny < n) {
                                if (isInfected[nx][ny] === 1) {
                                    queue.push([nx, ny]);
                                    isInfected[nx][ny] = -idx;
                                } else if (isInfected[nx][ny] === 0) {
                                    ++firewall;
                                    neighbor.add(getHash(nx, ny));
                                }
                            }
                        }
                    }
                    neighbors.push(neighbor);
                    firewalls.push(firewall);
                }
            }
        }

        if (neighbors.length === 0) {
            break;
        }

        let idx = 0;
        for (let i = 1; i < neighbors.length; ++i) {
            if (neighbors[i].size > neighbors[idx].size) {
                idx = i;
            }
        }
        ans += firewalls[idx];
        for (let i = 0; i < m; ++i) {
            for (let j = 0; j < n; ++j) {
                if (isInfected[i][j] < 0) {
                    if (isInfected[i][j] !== -idx - 1) {
                        isInfected[i][j] = 1;
                    } else {
                        isInfected[i][j] = 2;
                    }
                }
            }
        }
        for (let i = 0; i < neighbors.length; ++i) {
            if (i !== idx) {
                for (const val of neighbors[i]) {
                    let x = val >> 16, y = val & ((1 << 16) - 1);
                    isInfected[x][y] = 1;
                }
            }
        }
        if (neighbors.length === 1) {
            break;
        }
    }
    return ans;
}

const getHash = (x, y) => {
    return (x << 16) ^ y;
};

千分位算法

数字有小数

let format = n => {
    let num = n.toString() // 转成字符串
    let decimals = ''
        // 判断是否有小数
    num.indexOf('.') > -1 ? decimals = num.split('.')[1] : decimals
    let len = num.length
    if (len <= 3) {
        return num
    } else {
        let temp = ''
        let remainder = len % 3
        decimals ? temp = '.' + decimals : temp
        if (remainder > 0) { // 不是3的整数倍
            return num.slice(0, remainder) + ',' + num.slice(remainder, len).match(/\d{3}/g).join(',') + temp
        } else { // 是3的整数倍
            return num.slice(0, len).match(/\d{3}/g).join(',') + temp 
        }
    }
}
format(12323.33)  // '12,323.33'

数字无小数

let format = n => {
    let num = n.toString() 
    let len = num.length
    if (len <= 3) {
        return num
    } else {
        let remainder = len % 3
        if (remainder > 0) { // 不是3的整数倍
            return num.slice(0, remainder) + ',' + num.slice(remainder, len).match(/\d{3}/g).join(',') 
        } else { // 是3的整数倍
            return num.slice(0, len).match(/\d{3}/g).join(',') 
        }
    }
}
format(1232323)  // '1,232,323

一次循环取出数组重复的值

function duplicates(arr) {
    return arr.filter((e,i) => arr.indexOf(e)!==arr.lastIndexOf(e) && arr.indexOf(e)===i);
}

数组扁平化

数组拍平也称数组扁平化,就是将数组里面的数组打开,最后合并为一个数组

实现

var arr = [1, 2, [3, 4, 5, [6, 7, 8], 9], 10, [11, 12]];

a:递归实现

function fn(arr) {
    let arr1 = [];
    arr.forEach(val => {
        if (val instanceof Array) {
            arr1 = arr1.concat(fn(val));
        } else {
            arr1.push(val);
        }
    });
    return arr1;
}

b:reduce 实现

function fn(arr) {
    return arr.reduce((prev, cur) => {
        return prev.concat(Array.isArray(cur) ? fn(cur) : cur);
    }, []);
}

c:flat

参数为层数(默认一层)

arr.flat(Infinity);

d:扩展运算符

function fn(arr) {
    let arr1 = [];
    let bStop = true;
    arr.forEach(val => {
        if (Array.isArray(val)) {
            arr1.push(...val);
            bStop = false;
        } else {
            arr1.push(val);
        }
    });
    if (bStop) {
        return arr1;
    }
    return fn(arr1);
}

e:toString

let arr1 = arr
    .toString()
    .split(",")
    .map(val => {
        return parseInt(val);
    });
console.log(arr1);

f:apply

function flatten(arr) {
    while (arr.some(item => Array.isArray(item))) {
        arr = [].concat.apply([], arr);
    }
    return arr;
}

回文数

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 例如,121 是回文,而 123 不是。  

示例 1:

输入:x = 121
输出:true

示例 2:

输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

示例 3:

输入:x = 10
输出:false
解释:从右向左读, 为 01 。因此它不是一个回文数。
/**
 * @param {number} x
 * @return {boolean}
 */
 var isPalindrome = function (x) {

    let arr = x.toString()
    arr = arr.split("")
    let arrRe = arr.reverse()
    let str = arrRe.join("")
    if (str == x) return true
    return false
};

来源:力扣(LeetCode) 链接:leetcode.cn/problems/pa…

两数之和

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

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

你可以按任意顺序返回答案。

示例 1:

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

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]
var twoSum = function(nums, target) {
    let map = new Map();
    for(let i = 0, len = nums.length; i < len; i++){
        if(map.has(target - nums[i])){
            return [map.get(target - nums[i]), i];
        }else{
            map.set(nums[i], i);
        }
    }
    return [];
};

来源:力扣(LeetCode) 链接:leetcode.cn/problems/tw…

二维网格迁移

给你一个 m 行 n 列的二维网格 grid 和一个整数 k。你需要将 grid 迁移 k 次。

每次「迁移」操作将会引发下述活动:

位于 grid[i][j] 的元素将会移动到 grid[i][j + 1]。 位于 grid[i][n - 1] 的元素将会移动到 grid[i + 1][0]。 位于 grid[m - 1][n - 1] 的元素将会移动到 grid[0][0]。 请你返回 k 次迁移操作后最终得到的 二维网格。

示例 1:

image.png

输入:grid = [[1,2,3],[4,5,6],[7,8,9]], k = 1
输出:[[9,1,2],[3,4,5],[6,7,8]]

示例 2:

image.png

输入:grid = [[3,8,1,9],[19,7,2,5],[4,6,11,10],[12,0,21,13]], k = 4
输出:[[12,0,21,13],[3,8,1,9],[19,7,2,5],[4,6,11,10]]

示例 3:

输入:grid = [[1,2,3],[4,5,6],[7,8,9]], k = 9
输出:[[1,2,3],[4,5,6],[7,8,9]]
/**
 * @param {number[][]} grid
 * @param {number} k
 * @return {number[][]}
 */
var shiftGrid = function (grid, k) {

    let arr = grid.flat(Infinity)
    k = k % arr.length
    if (k) {
        let arr1 = arr.slice(-k).concat(arr.slice(0, arr.length - k))
        let m = grid[0].length
        let newArr = new Array()
        for (let i = 0; i < grid.length; i++) {
            newArr.push(arr1.slice(i * m, (i + 1) * m))
        }
        return newArr
    } else {
        return grid
    }
};

来源:力扣(LeetCode) 链接:leetcode.cn/problems/sh…

罗马数字转整数

罗马数字包含以下七种字符: 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:

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

示例 2:

输入: s = "IV"
输出: 4

示例 3:

输入: s = "IX"
输出: 9

示例 4:

输入: s = "LVIII"
输出: 58
解释: L = 50, V= 5, III = 3.

示例 5:

输入: s = "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.
/**
 * @param {string} s
 * @return {number}
 */
var romanToInt = function (s) {
    let map = new Map()
    let num = 0

    map.set("I", 1)
    map.set("V", 5)
    map.set("X", 10)
    map.set("L", 50)
    map.set("C", 100)
    map.set("D", 500,)
    map.set("M", 1000)

    for (let i = s.length - 1; i >= 0; i--) {
        let curr = s[i]
        let pre = i > 0 ? s[i - 1] : 0
        if (map.get(pre) < map.get(curr)) {
            num += map.get(curr) - map.get(pre)
            i--
        } else {
            num += map.get(curr)
        }
    }
    return num
};

来源:力扣(LeetCode) 链接:leetcode.cn/problems/ro…

最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""。

示例 1:

输入:strs = ["flower","flow","flight"]
输出:"fl"

示例 2:

输入:strs = ["dog","racecar","car"]
输出:""
解释:输入不存在公共前缀。

方法一:字典

/**
 * @param {string[]} strs
 * @return {string}
 */
var longestCommonPrefix = function (strs) {
    let map = new Map()
    let str = ""
    let commonPre = { key: '', value: strs.length }

    if (strs.length > 1) {
        for (let i = 0; i < strs.length; i++) {
            let str = strs[i]
            for (let j = 0; j < str.length; j++) {
                let char = str.slice(0, j + 1)
                if (map.has(char)) {
                    let val = map.get(char) + 1
                    if (val >= commonPre.value) {
                        commonPre = {
                            key: char,
                            value: val
                        }

                    }
                    map.set(char, val)
                } else {
                    map.set(char, 1)
                }
            }
        }
    } else {
        return strs[0]
    }

    return commonPre.key
};

解法二

思路:一一对比,不满足跳出

/**
 * @param {string[]} strs
 * @return {string}
 */
var longestCommonPrefix = function (strs) {
    if (strs.length === 1) return strs[0]
    let ans = strs[0]
    for (let i = 1; i < strs.length; i++) {
        let curr = strs[i]
        if (!curr) {
            return ""
        }
        let j = 0
        for (; j < ans.length && j < curr.length; j++) {
            if (ans[j] != curr[j]) break
        }
        ans = ans.slice(0, j)

    }
    return ans
};

来源:力扣(LeetCode) 链接:leetcode.cn/problems/lo…

二叉树剪枝

给你二叉树的根结点 root ,此外树的每个结点的值要么是 0 ,要么是 1 。

返回移除了所有不包含 1 的子树的原二叉树。

节点 node 的子树为 node 本身加上所有 node 的后代。

示例 1:

image.png

输入:root = [1,null,0,0,1]
输出:[1,null,0,null,1]
解释:
只有红色节点满足条件“所有不包含 1 的子树”。 右图为返回的答案。

示例 2: image.png

输入:root = [1,0,1,0,0,0,1]
输出:[1,null,1,null,1]

示例 3:

image.png

输入:root = [1,1,0,1,1,0,1,0]
输出:[1,1,0,1,1,null,1]

题解

/**
 * @param {TreeNode} root
 * @return {TreeNode}
 */
var pruneTree = function (root) {

    if (!root) {
        return null
    }
    root.left = pruneTree(root.left)
    root.right = pruneTree(root.right)

    if (!root.left && !root.right && root.val === 0) {
        return null
    }
    return root
};

来源:力扣(LeetCode) 链接:leetcode.cn/problems/bi…

有效的括号

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

有效字符串需满足:

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

示例 1:

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

示例 2:

输入:s = "()[]{}"
输出:true

示例 3:

输入:s = "(]"
输出:false

示例 4:

输入:s = "([)]"
输出:false

示例 5:

输入:s = "{[]}"
输出:true

自解

/**
 * @param {string} s
 * @return {boolean}
 */
var isValid = function (s) {
    if(s.length<=1) return false
    let map = new Map()
    map.set(")","(")
    map.set( "]","[")
    map.set( "}","{")

    let stack = []
    for (let i = 0; i < s.length; i++) {
        if (stack.length && map.get(s[i]) === stack[stack.length-1]) {
            stack.pop(s[i - 1])
        } else {
            stack.push(s[i])
        }
    }

    if (!stack.length) {
        return true
    }
    return false
};

官方解法

/**
 * @param {string} s
 * @return {boolean}
 */
var isValid = function (s) {
    if (s % 2) return false
    let map = new Map([
        [')', '('],
        [']', '['],
        ['}', '{']
    ]
    )

    let stack = []

    for (let i of s) {
        if (map.has(i)) {
            if (!stack.length || map.get(i) !== stack[stack.length - 1]) {
                stack.push(i)
            } else {
                stack.pop()
            }
        } else {
            stack.push(i)
        }

    }
    if (!stack.length) {
        return true
    }
    return false
};

来源:力扣(LeetCode) 链接:leetcode.cn/problems/va…

合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

image.png

示例 1:

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例 2:

输入:l1 = [], l2 = []
输出:[]

示例 3:

输入:l1 = [], l2 = [0]
输出:[0]
function ListNode(val, next) {
    this.val = (val === undefined ? 0 : val)
    this.next = (next === undefined ? null : next)
}
/**
 * @param {ListNode} list1
 * @param {ListNode} list2
 * @return {ListNode}
 */
var mergeTwoLists = function (list1, list2) {
    if (list1 === null) {
        return list2
    } else if (list2 === null) {
        return list1
    } else if (list1.val < list2.val) {
        list1.next = mergeTwoLists(list1.next,list2)
        return list1
    } else {
        list2.next = mergeTwoLists(list1,list2.next)
        return list2 
    }

};

来源:力扣(LeetCode) 链接:leetcode.cn/problems/me…

new

sleep