leetcode刷题-双指针

300 阅读3分钟

双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务。

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

题目

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

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

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

var twoSum = function(numbers, target) {
  let left = 0, right = numbers.length - 1;
  let result = [];

  while(right > left) {
    let sum = numbers[left] + numbers[right];
    if (sum === target) {
      result.push(left + 1, right + 1);
      return result;
    } else if (sum > target) {
      right--;
    } else {
      left++;
    }
  }
  return result;
};

2. 平方数之和

题目

给定一个非负整数 c ,你要判断是否存在两个整数 ab,使得 a2 + b2 = c

/**
 * @param {number} c
 * @return {boolean}
 */
var judgeSquareSum = function(c) {
  let left = 0, right = Math.ceil(Math.sqrt(c));
  while(right >= left) {
    let value = left * left + right * right;
    if (value === c) {
      return true;
    } else if (value > c) {
      right--;
    } else {
      left++;
    }
  }
  return false;
};

3. 反转字符串中的元音字母

题目

编写一个函数,以字符串作为输入,反转该字符串中的元音字母。

/**
 * @param {string} s
 * @return {string}
 */
var reverseVowels = function(s) {
  const sets = new Set(['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']);

  let resArr = s.split('');
  let left = 0, right = resArr.length - 1;

  while(right > left) {
    const leftFlag = sets.has(resArr[left]);
    const rightFlag = sets.has(resArr[right]);

    if (leftFlag && rightFlag) {
      swap(resArr, left, right);
      left++;
      right--;
    } else if (leftFlag) {
      right--;
    } else {
      left++;
    }
  }
  return resArr.join('');
};

function swap(arr, i, j) {
  const temp = arr[i];
  arr[i] = arr[j];
  arr[j] = temp;
}

4. 验证回文字符串 Ⅱ

题目

给定一个非空字符串 s最多删除一个字符。判断是否能成为回文字符串。

/**
 * @param {string} s
 * @return {boolean}
 */
var validPalindrome = function(s) {
  let left = 0, right = s.length - 1;
  while(right > left) {
    if (s.charAt(left) !== s.charAt(right)) {
      return isPalindrome(s, left + 1, right) || isPalindrome(s, left, right - 1);
    }
    right--;
    left++;
  }
  return true;
};

function isPalindrome(str, left, right) {
  while(right > left) {
    if (str.charAt(left) !== str.charAt(right)) {
      return false;
    }
    left++;
    right--;
  }
  return true;
}

5. 合并两个有序数组

题目

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

初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。

// 注意要从数组后面往前遍历
var merge = function(nums1, m, nums2, n) {
  let index1 = m - 1, index2 = n - 1, index = m + n - 1;

  while(index1 !== -1 || index2 !== -1) {
    if (index1 === -1) {
      nums1[index--] = nums2[index2--];
    } else if (index2 === -1) {
      nums1[index--] = nums1[index1--];
    } else if (nums2[index2] > nums1[index1]) {
      nums1[index--] = nums2[index2--];
    } else {
      nums1[index--] = nums1[index1--];
    }
  }
};

6. 环形链表

题目

给定一个链表,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

如果链表中存在环,则返回 true 。 否则,返回 false 。

// 快慢指针
var hasCycle = function(head) {
  if (!head) return false;

  let slow = head, fast = head;

  while(slow && fast) {
    slow = slow.next;
    if (!fast.next) {
      return false;
    } 
    fast = fast.next.next;
    if (slow === fast) {
      return true;
    }
  }

  return false;
};

7. 通过删除字母匹配到字典里最长单词

题目

给你一个字符串 s 和一个字符串数组 dictionary 作为字典,找出并返回字典中最长的字符串,该字符串可以通过删除 s 中的某些字符得到。

如果答案不止一个,返回长度最长且字典序最小的字符串。如果答案不存在,则返回空字符串。

var findLongestWord = function(s, dictionary) {
  let maxLength = 0, res = '';
  dictionary.forEach(item => {
    if (isSubString(s, item)) {
      if (item.length > maxLength) {
        maxLength = item.length;
        res = item;
      } else if (item.length === maxLength) {
        res = item > res ? res : item;
      }
    }
  })
  return res;
};


function isSubString(str, subStr) {
  let index = 0, subIndex = 0;
  let strLength = str.length, subLength = subStr.length;

  while(index < strLength) {
    if (subIndex === subLength) {
      return true;
    }
    if (str[index] === subStr[subIndex]) {
      subIndex++;
    } 
    index++;
  }
  return subIndex === subLength;
}