算法学习day17(字符串)

一、反转字符串中的单词III

题意:

给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

输入:s = "Let's take LeetCode contest"
输出:"s'teL ekat edoCteeL tsetnoc"
思路:

反转字符串的时候需要知道每个单词的startIndex和endIndex。通过String类的split方法将空格删去,然后计算出每一个单词的size。startIndex=endInedx+2;要把空格算上(当然起始是0);然后endIndex=startIndex+spilt[i].length()-1;

代码:
class Solution {
    public String reverseWords(String s) {
        char[] ch = s.toCharArray();
        String[] split = s.split(" ");
        int startIndex = 0;
        for (int i = 0; i < split.length; i++) {
            int endIndex = startIndex + split[i].length() - 1;
            reverse(ch, startIndex, endIndex);
            startIndex=endIndex+2;
        }
        return new String(ch);
    }

    public void reverse(char[] ch,int left,int right){
        while(left<right){
            char temp=ch[left];
            ch[left]=ch[right];
            ch[right]=temp;
            left++;
            right--;
        }
    }
}

二、反转字符串中的单词(新思路)

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

思路:

1.首先将首尾的空格删除;str.trim();然后split(" ");

2.然后使用StringBuilder从后往前拼接字符串,如果split[i]=="",直接下一个。直到遇到单词,就把它加进去,然后再append(" ");

代码:
class Solution {
    public String reverseWords(String s) {
        //先将整个字符串反转
        String str=s.trim();
        String[] strs=str.split(" ");
        StringBuilder sb=new StringBuilder();
        for(int i=strs.length-1;i>=0;i--){
            if(strs[i].equals(""))continue;
            sb.append(strs[i]+" ");
        }
        return sb.toString().trim();
        
    }
}

三、字母异位词分组(使用map存储)

题意:

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
思路:

字母异位词的字母是一样的,只是顺序不一样。通过toCharArray()后,使用Arrays.sort();

就可以按照字符排序。所以使用map键值对来存。key:String(按照字符排序后的字符串),value:字母一样的集合。

每当遍历一个字符串:str.toCharArray(); 然后:Arrays.sort(ch);然后 String key=new String(ch);

然后要判断集合中是否有这个key,如果没有要先创建集合;如果有直接加入。map.get(key).add(str);

代码:
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        if(strs==null||strs.length==0)return new ArrayList<>();
        //使用map,key:字符串按照字符排序 value:存储拥有相同键的字符串的集合
        Map<String,List<String>> map=new HashMap<>();
        for(String str:strs){
            //首先将str排序
            char[] chs=str.toCharArray();
            Arrays.sort(chs);
            String key=new String(chs);
            //看有没有这个
            if(!map.containsKey(key)){
                map.put(key,new ArrayList<>());
            }
            map.get(key).add(str);
        }
        return new ArrayList<>(map.values());
    }
}

四、根据字符出现频率排序(哈希表)

思路:

1.首先一次for循环遍历记录字符出现的频率

2.其次获取map集合的键的集合keySet并且将这个集合根据value排序(重点)

3.然后遍历集合,使用StringBuilder根据value的值,拼接ch value次。

代码:
class Solution {
    public String frequencySort(String s) {
        //记录每一个字符出现的次数
        HashMap<Character,Integer> map=new HashMap<>();
        for(int i=0;i<s.length();i++){
            char ch=s.charAt(i);
            map.put(ch,map.getOrDefault(ch,0)+1);
        }
        //获取key的集合
        List<Character> list=new ArrayList<Character>(map.keySet());
        //根据key对应的value进行降序排序 nb
        Collections.sort(list,(a,b)->map.get(b)-map.get(a));
        //遍历拼接字符串
        StringBuilder sb=new StringBuilder();
        for(int i=0;i<list.size();i++){
            char ch=list.get(i);
            int number=map.get(ch);
            for(int j=0;j<number;j++){
                sb.append(ch);
            }
        }
        return sb.toString();
    }
}

五、计数二进制子串

题意:

给定一个字符串 s,统计并返回具有相同数量 0 和 1 的非空(连续)子字符串的数量,并且这些子字符串中的所有 0 和所有 1 都是成组连续的。

重复出现(不同位置)的子串也要统计它们出现的次数。

思路:

题目中要求的是:具有相同数量0和1的非空连续子字符串的数量。eg:00011,这五个字符中0和1的个数分别是3,2。连续子字符串的数量有:01 0011两个。因此每一对相邻二进制串的拥有相同数量的0,1的xxx的数量是Math.min(0数量,1数量);

代码:
class Solution {
    public int countBinarySubstrings(String s){
        int size=s.length();
        int[] counts=new int[size];
        int index=0;
        counts[0]=1;
        //首先对字符串中的01计数
        for(int i=0;i<size;i++){
            if(i+1<size&&s.charAt(i)==s.charAt(i+1)){
                counts[index]++;
            }else if(i+1<size&&s.charAt(i)!=s.charAt(i+1)){
                index++;
                counts[index]=1;
            }
        }
        int sum=0;
        for(int i=0;i<size-1;i++){
            sum+=Math.min(counts[i],counts[i+1]);
        }
        return sum;
    }
}

  • 22
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值