leetcode刷题记录(28)-简单

1.仅仅反转字母

题目:给定一个字符串 S,返回 “反转后的” 字符串,其中不是字母的字符都保留在原地,而所有字母的位置发生反转。

思路:双指针法,记录两边的字符串拼接结果,左指针和右指针遇到字母时,交换各自位置上的字符,遇到其他字符正常拼接,直到相遇

/**
 * @param {string} S
 * @return {string}
 */
var reverseOnlyLetters = function(S) {
  let left = 0,
    right = S.length - 1;
  let LS = "";
  let RS = "";
  const reg = /[a-zA-Z]/;
  while (left < right) {
    while (!reg.test(S[left]) && left < right) {
      LS += S[left];
      left++;
    }
    while (!reg.test(S[right]) && left < right) {
      RS = `${S[right]}${RS}`;
      right--;
    }
    if (left >= right) break;
    LS += S[right];
    RS = `${S[left]}${RS}`;
    left++;
    right--;
  }
  if (left === right) {
    LS += S[left];
  }
  return `${LS}${RS}`;
};

也可以分割成数组,用双指针法交换数组上两个位置的字符然后拼接

/**
 * @param {string} S
 * @return {string}
 */
var reverseOnlyLetters = function(S) {
  let left = 0,
    right = S.length - 1;
  const res=S.split("")
  const reg = /[a-zA-Z]/;
  while (left < right) {
    while (!reg.test(S[left]) && left < right) {
      left++;
    }
    while (!reg.test(S[right]) && left < right) {
      right--;
    }
    if (left >= right) break;
    [res[left],res[right]]=[res[right],res[left]]
    left++;
    right--;
  }

  return res.join("")
};

2.按奇偶排序数组

题目:

给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。

对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。

你可以返回任何满足上述条件的数组作为答案。

思路:还是双指针法,一个指针记录奇数位上的数字,一个记录偶数位上的数字,遇到偶数位上是奇数停,另一个一样,然后交换。

/**
 * @param {number[]} A
 * @return {number[]}
 */
var sortArrayByParityII = function(A) {
  let a = 0,
    b = 0;
  while (a < A.length / 2) {
    while (a < A.length / 2 && !(A[2 * a] % 2)) {
      a++;
    }
    while (b < A.length / 2 && A[2 * b + 1] % 2) {
      b++;
    }
    if (a >= A.length / 2 || b >= A.length / 2) break;
    [A[2 * a], A[2 * b + 1]] = [A[2 * b + 1], A[2 * a]];
  }

  return A;
};

3.长按键入

题目:

你的朋友正在使用键盘输入他的名字 name。偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次。

你将会检查键盘输入的字符 typed。如果它对应的可能是你的朋友的名字(其中一些字符可能被长按),那么就返回 True。

思路:双指针各自指向两个字符串的开头,然后依次比较字符,遇到不同的字符,第二个指针往后遍历,直到移动到与当前字符不同的位置,这时如果还不同,则返回false。第一个字符串如果遍历结束,第二个字符串也要进行移动,直到移动到与当前字符不同的位置。这时比较第二个字符的位置,如果右侧仍有字符,则不符合条件

/**
 * @param {string} name
 * @param {string} typed
 * @return {boolean}
 */
var isLongPressedName = function(name, typed) {
  const l = name.length;
  const lr = typed.length;
  if (l > lr) return false;
  let r = 0;
  for (let i = 0; i < l; i++) {
    if (name[i] !== typed[r]) {
      while (typed[r] == typed[r - 1]) {
        r++;
      }
      if (r >= lr) return false;
      if (name[i] !== typed[r]) return false;
    }
    r++;
  }
  while (typed[r] == typed[r - 1]) {
    r++;
  }
  return r >= lr;
};

4.独特的电子邮件地址

题目:

每封电子邮件都由一个本地名称和一个域名组成,以 @ 符号分隔。

例如,在 alice@leetcode.com中, alice 是本地名称,而 leetcode.com 是域名。

除了小写字母,这些电子邮件还可能包含 '.' 或 '+'。

如果在电子邮件地址的本地名称部分中的某些字符之间添加句点('.'),则发往那里的邮件将会转发到本地名称中没有点的同一地址。例如,"alice.z@leetcode.com” 和 “alicez@leetcode.com” 会转发到同一电子邮件地址。 (请注意,此规则不适用于域名。)

如果在本地名称中添加加号('+'),则会忽略第一个加号后面的所有内容。这允许过滤某些电子邮件,例如 m.y+name@email.com 将转发到 my@email.com。 (同样,此规则不适用于域名。)

可以同时使用这两个规则。

给定电子邮件列表 emails,我们会向列表中的每个地址发送一封电子邮件。实际收到邮件的不同地址有多少?

思路:解析本地名称,遇到'@',则直接拼接后面的,遇到'+',忽略后面的,遇到'.'就跳过。注意这三个优先级是从高到低的。

然后用set记录

/**
 * @param {string[]} emails
 * @return {number}
 */
var numUniqueEmails = function(emails) {
  const adress = new Set();
  for (const n of emails) {
    const l = n.length;
    let s = "";
    let flag = false;
    for (let i = 0; i < l; i++) {
      if (n[i] == "@") {
        s += n.slice(i);
        break;
      } else if (!flag) {
        if (n[i] == "+") {
          flag = true;
        } else if (n[i] !== ".") {
          s += n[i];
        }
      }
    }
    adress.add(s);
  }
  return adress.size;
};

也可以分割字符串,先替换'.',然后用'+'分割

/**
 * @param {string[]} emails
 * @return {number}
 */
var numUniqueEmails = function(emails) {
    return [...new Set(emails.map(item => {
      let list = item.split('@')
      list[0] = list[0].replace(/\./g,'').split('+')[0]
      return list.join('@')
    }))].length
};

5.最近的请求次数

写一个 RecentCounter 类来计算最近的请求。

它只有一个方法:ping(int t),其中 t 代表以毫秒为单位的某个时间。

返回从 3000 毫秒前到现在的 ping 数。

任何处于 [t - 3000, t] 时间范围之内的 ping 都将会被计算在内,包括当前(指 t 时刻)的 ping。

保证每次对 ping 的调用都使用比之前更大的 t 值。

思路:维护一个队列,每次Ping的时候,对小于t-3000的成员出列

var RecentCounter = function() {
  this.list = [];
};

/** 
 * @param {number} t
 * @return {number}
 */
RecentCounter.prototype.ping = function(t) {
  this.list.push(t);
  while(this.list[0]<t-3000){
      this.list.shift()
  }
  return this.list.length
};

/**
 * Your RecentCounter object will be instantiated and called as such:
 * var obj = new RecentCounter()
 * var param_1 = obj.ping(t)
 */

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值