特斯拉笔试 2023/3/22 19:30


859. 亲密字符串

给你两个字符串 s 和 goal ,只要我们可以通过交换 s 中的两个字母得到与 goal 相等的结果,就返回 true ;否则返回 false 。
交换字母的定义是:取两个下标 i 和 j (下标从 0 开始)且满足 i != j ,接着交换 s[i] 和 s[j] 处的字符。
例如,在 "abcd" 中交换下标 0 和下标 2 的元素可以生成 "cbad" 。
 
示例 1:

输入:s = "ab", goal = "ba"
输出:true
解释:你可以交换 s[0] = 'a' 和 s[1] = 'b' 生成 "ba",此时 s 和 goal 相等。
示例 2:

输入:s = "ab", goal = "ab"
输出:false
解释:你只能交换 s[0] = 'a' 和 s[1] = 'b' 生成 "ba",此时 s 和 goal 不相等。
示例 3:

输入:s = "aa", goal = "aa"
输出:true
解释:你可以交换 s[0] = 'a' 和 s[1] = 'a' 生成 "aa",此时 s 和 goal 相等。
 
提示:
1 <= s.length, goal.length <= 2 * 10^4
s 和 goal 由小写英文字母组成

解答:分类讨论

class Solution {
    public boolean buddyStrings(String s, String goal) {
         if(s.length()!=goal.length())return false;
          int[] res=new int[26];
          int[] res1=new int[26];
          //统计不一样的位置
          int a=0;
          for(int i=0;i<s.length();i++){
              char c=s.charAt(i);
              char c1=goal.charAt(i);
              if(c!=c1)a++;
              res[c-'a']++;
              res1[c1-'a']++;
          }
          //看有没有字母出现了两次以上
          int b=0;
          boolean flag=true;
          for(int i=0;i<26;i++){
              b=Math.max(b,res[i]);
              if(res[i]!=res1[i])flag=false;
          }
          if(!flag)return false;
          //如果都相等并且有字母出现过两次
          if(a==0&&b>=2)return true;
          if(a==2)return true;
          return false;
    }
}

1419. 数青蛙

给你一个字符串 croakOfFrogs,它表示不同青蛙发出的蛙鸣声(字符串 "croak" )的组合。由于同一时间可以有多只青蛙呱呱作响,所以 croakOfFrogs 中会混合多个 “croak” 。
请你返回模拟字符串中所有蛙鸣所需不同青蛙的最少数目。
要想发出蛙鸣 "croak",青蛙必须 依序 输出 ‘c’, ’r’, ’o’, ’a’, ’k’ 这 5 个字母。如果没有输出全部五个字母,那么它就不会发出声音。如果字符串 croakOfFrogs 不是由若干有效的 "croak" 字符混合而成,请返回 -1 。

示例 1:

输入:croakOfFrogs = "croakcroak"
输出:1 
解释:一只青蛙 “呱呱” 两次
示例 2:

输入:croakOfFrogs = "crcoakroak"
输出:2 
解释:最少需要两只青蛙,“呱呱” 声用黑体标注
第一只青蛙 "crcoakroak"
第二只青蛙 "crcoakroak"
示例 3:

输入:croakOfFrogs = "croakcrook"
输出:-1
解释:给出的字符串不是 "croak" 的有效组合。
 
提示:
1 <= croakOfFrogs.length <= 105
字符串中的字符只有 'c', 'r', 'o', 'a' 或者 'k'

解答:暴力枚举,每次判断是否合法

class Solution {
    public int minNumberOfFrogs(String croakOfFrogs) {
       int[] h=new int[26];
       int res=0;
       int cc=0,r=0,o=0,a=0,k=0;
       for(char c:croakOfFrogs.toCharArray()){
          if(c=='c'){
              cc++;
              res=Math.max(res,cc-k);
          }
          else if(c=='r'){
              if(cc>r)r++;
              else return -1;
          }
          else if(c=='o'){
               if(r>o)o++;
               else return -1;
          }
          else if(c=='a'){
               if(o>a)a++;
               else return -1;
          }
          else{
              if(a>k)k++;
              else return -1;
          }
       }
       //都要相等才能返回res
       if(cc==r&&r==o&&o==a&&a==k)return res;
       return -1;
    }
}

剑指 Offer II 087. 复原 IP

给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能从 s 获得的 有效 IP 地址 。你可以按任何顺序返回答案。

有效 IP 地址 正好由四个整数(每个整数位于 0255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。

例如:"0.1.2.201""192.168.1.1" 是 有效 IP 地址,但是 "0.011.255.245""192.168.1.312""192.168@1.1" 是 无效 IP 地址。

示例 1:

输入:s = "25525511135"
输出:["255.255.11.135","255.255.111.35"]
示例 2:

输入:s = "0000"
输出:["0.0.0.0"]
示例 3:

输入:s = "1111"
输出:["1.1.1.1"]
示例 4:

输入:s = "010010"
输出:["0.10.0.10","0.100.1.0"]
示例 5:

输入:s = "10203040"
输出:["10.20.30.40","102.0.30.40","10.203.0.40"]
 

提示:
0 <= s.length <= 3000
s 仅由数字组成

解答:直接回溯,判断每次的结果是否合法,合法就加到答案里

class Solution {
        List<String> res=new ArrayList<>();
    public List<String> restoreIpAddresses(String s) {
        if(s.length()>12)return res;
        backing(s,0,0);
        return res;
    }
    private void backing(String s,int pointNum,int start){
        if(pointNum==3){
            if(isVaild(s,start,s.length()-1)){
            res.add(s);
            return;
            }
        }
        for(int i=start;i<s.length();i++){
            //判断区间[start,i]是否合法
            if(isVaild(s,start,i)){
                s=s.substring(0,i+1)+"."+s.substring(i+1);
                pointNum++;
                backing(s,pointNum,i+2);
                pointNum--;
                s=s.substring(0,i+1)+s.substring(i+2);//回溯,删除'.';
            }
            else break;
        }
    }
    //判断ip地址是否合法
    private boolean isVaild(String s,int start,int end){
        if(start>end)return false;
        //首位为0,不合法
        if(start!=end&&s.charAt(start)=='0')return false;
        int num=0;
        for(int i=start;i<=end;i++){
            if(s.charAt(i)<'0'&&s.charAt(i)>'9')return false;
            num=s.charAt(i)-'0'+10*num;
            if(num<0||num>255)return false;
        }
        return true;
    }
}

630. 课程表 III

这里有 n 门不同的在线课程,按从 1 到 n 编号。给你一个数组 courses ,其中 courses[i] = [durationi, lastDayi] 表示第 i 门课将会 持续 上 durationi 天课,并且必须在不晚于 lastDayi 的时候完成。
你的学期从第 1 天开始。且不能同时修读两门及两门以上的课程。
返回你最多可以修读的课程数目。

示例 1:

输入:courses = [[100, 200], [200, 1300], [1000, 1250], [2000, 3200]]
输出:3
解释:
这里一共有 4 门课程,但是你最多可以修 3 门:
首先,修第 1 门课,耗费 100 天,在第 100 天完成,在第 101 天开始下门课。
第二,修第 3 门课,耗费 1000 天,在第 1100 天完成,在第 1101 天开始下门课程。
第三,修第 2 门课,耗时 200 天,在第 1300 天完成。
第 4 门课现在不能修,因为将会在第 3300 天完成它,这已经超出了关闭日期。
示例 2:

输入:courses = [[1,2]]
输出:1
示例 3:

输入:courses = [[3,2],[4,3]]
输出:0
 
提示:
1 <= courses.length <= 10^4
1 <= durationi, lastDayi <= 10^4

解答:贪心+排序+大顶堆

class Solution {
    public int scheduleCourse(int[][] courses) {
        Arrays.sort(courses,(a,b)->a[1]-b[1]);
        //大顶堆
        PriorityQueue<Integer> pq=new PriorityQueue<>((a,b)->(b-a));
        int res=0;
        for(int[] c:courses){
            int d=c[0],e=c[1];
            res+=d;
            pq.offer(d);
            //当前不满足要求时,直接返回最大的那个时间段
            if(res>e)res-=pq.poll();
        }
        return pq.size();
    }
}

  目录