求链表中间节点¶
统计信息:字数 3938 阅读8分钟
判断回文链表¶
请判断一个单链表是否为回文链表。
示例1:
输入: 1->2
输出: false
示例2:
输入: 1->2->2->1
输出: true
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
来源: LeetCode第234题
思路分析¶
这一题如果不考虑性能的限制,其实是非常简单的。但考虑到 O(n) 时间复杂度和 O(1) 空间复杂度,恐怕就值得停下来好好想想了。
题目的要求是单链表,没有办法访问前面的节点,那我们只得另辟蹊径:
找到链表中点,然后将后半部分反转,就可以依次比较得出结论了。下面我们来实现一波。
代码实现¶
其实关键部分的代码就是找中点了。先亮剑:
let dummyHead = slow = fast = new ListNode();
dummyHead.next = head;
// 注意,找中点
while(fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
}
你可能会纳闷了,为什么边界要设成这样?
我们不妨来分析一下,分链表节点个数为奇数和偶数的时候分别讨论。对于 fast 为空和fast.next为空两个条件,在奇数的情况下,总是 fast为空先出现,偶数的情况下,总是fast.next先出现.
也就是说: 一旦fast为空, 链表节点个数一定为奇数,否则为偶数。因此两种情况可以合并来讨论,当 fast 为空或者 fast.next 为空,循环就可以终止了。
完整实现如下:
/**
* @param {ListNode} head
* @return {boolean}
*/
var isPalindrome = function(head) {
// 交换链表的两项(反转列表)
let reverse = (pre, cur) => {
if (!cur) {
return pre;
}
let next = cur.next;
cur.next = pre;
return reverse(cur, next);
}
let dummyHead = slow = fast = new ListNode();
dummyHead.next = head;
// 注意,找中点,
while (fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
}
let next = slow.next;
slow.next = null;
let newStart = reverse(null, next);
for (let p = head, newP = newStart; newP != null; p = p.next, newP = newP.next) {
if (p.val != newP.val) {
return false;
}
}
return true;
};
栈和队列¶
有效括号¶
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
有效字符串需满足:左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 注意空字符串可被认为是有效字符串。
示例:
输入: "()"
输出: true
来源: LeetCode第20题
代码实现
/**
* @param {string} s
* @return {boolean}
*/
var isValid = function(s) {
let stack = [];
for(let i = 0; i < s.length; i++) {
let ch = s.charAt(i);
if(ch == '(' || ch == '[' || ch == '{') {
stack.push(ch);
}
if(!stack.length) {
return false;
}
if(ch == ')' && stack.pop() !== '(') {
return false;
}
if(ch == ']' && stack.pop() !== '[' ) {
return false;
}
if(ch == '}' && stack.pop() !== '{') {
return false;
}
}
return stack.length === 0;
};
多维数组 flatten¶
将多维数组转化为一维数组。广度优先遍历+递归。
示例:
[1, [2, [3, [4, 5]]], 6] -> [1, 2, 3, 4, 5, 6]
代码实现
/**
* @constructor
* @param {NestedInteger[]} nestedList
* @return {Integer[]}
*/
let flatten = (nestedList) => {
let result = [];
let fn = function (target, ary) {
for (let i = 0; i < ary.length; i++) {
let item = ary[i];
if (Array.isArray(item)) {
fn(target, item);
} else {
target.push(item);
}
}
}
fn(result, nestedList)
return result;
}
同时可采用 reduce 的方式, 一行就可以解决,非常简洁。
let flatten = (nestedList) => {
nestedList.reduce((pre, cur) => pre.concat(Array.isArray(cur) ? flatten(cur): cur), []);
};
Last update:
November 9, 2024