//快慢指针:两个指针同向移动,但步长不同。适用场:判断链表是否有环、寻找链表中点、删除倒数第N个节点
//对撞指针:两个指针从序列两端出发,相向移动,直至碰面。适用场景:有序数组的两数之和、反转字符串、回文判断
//滑动窗口:两个指针作为窗口的左右边界,同向移动以维护一个连续区间。适用场景:最小覆盖子串、无重复字符的最长子串、长度最小的子数组
//-------判断链表是否有环:快慢指针----
/*
在拿到这道题的时候,完全是看不懂的,链表是个啥比较抽象的东西,问了AI,把链表具象化为js代码,链表就是一个构造函数,里面定义了节点对象。
在js中,链表是通过对象来实现的。每个节点都是一个独立的对象,包含val属性存储数据,和next属性指向下一个节点
。而head是一个变量,它保存着第一个节点对象的内存地址引用*/
//构造函数,定义了每个链表节点对象应该有哪些属性
function ListNode(val) {
this.val = val;
this.next = null
}
var hasCycle = function(head) {
if(head==null || head.next === null){
return false
}
let slow=head;
let fast=head;
while(fast!=null || fast.next!==null) {
slow=slow.next //慢指针每次移动1步
fast=fast.next.next //快指针每次移动 2 步
if(slow==fast) {
return true //指针相遇,表明有环
}
}
return false
};
//使用 new关键字调用构造函数,创建一个具体的节点对象
let node1 = new ListNode(1)
let node2 = new ListNode(2)
let node3 = new ListNode(3)
let node4 = new ListNode(4)
let node5 = new ListNode(5)
node1.next = node2
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node2; // 形成环
console.log(hasCycle(node1)); // 输出:true
node5.next = null; //无环
console.log(hasCycle(node1)); // 输出:false
//------------反转字符串:对撞指针---------
var reverseString = function(s) {
let left = 0, right = s.length - 1;
while (left < right) {
// 传统方法:使用临时变量
//let temp = s[left];
//s[left] = s[right];
//s[right] = temp;
// 解构赋值,交换两个变量,交换左右指针所指的字符
[s[left], s[right]] = [s[right], s[left]];
left++;
right--;
}
return s;
};
// 示例
let arr = ["h","e","l","l","o"];
reverseString(arr);
console.log(arr); // 输出: ["o","l","l","e","h"]
//------------给定一个字符串s,请找出其中不含有重复字符的最长子串的长度:滑动窗口---------
/*
滑动窗口算法通过维护一个窗口(通常由左右指针 left和 right定义),动态调整窗口大小来寻找最优解
其基本逻辑是右指针 right用于扩展窗口,左指针 left用于收缩窗口
*/
var lengthOfLongestSubstring = function(s) {
let left = 0;
let maxLength = 0;
const charSet = new Set(); // 使用Set存储当前窗口中的字符,保证唯一性
// 右指针向右遍历
for (let right = 0; right < s.length; right++) {
const currentChar = s[right];
// 如果当前字符已在窗口中(即出现重复)
while (charSet.has(currentChar)) {
// 不断收缩左边界,直到移除那个重复的字符
charSet.delete(s[left]);
left++;
}
// 将当前字符加入窗口
charSet.add(currentChar);
// 更新最大长度 (right - left + 1 是当前窗口长度)
maxLength = Math.max(maxLength, right - left + 1);
}
return maxLength;
};
console.log(lengthOfLongestSubstring("abcabcbb")); // 输出: 3 ("abc")
console.log(lengthOfLongestSubstring("pwwkew")); // 输出: 3 ("wke")
console