算法学习day18(字符串)

一、环绕字符串中唯一的子字符串(线性dp)

题意:

有一个base串,是a-z重复循环的。然后给你一个字符串,看这个字符串的子串是base串中出现的次数。

输入:s = "zab"
输出:6
解释:字符串 s 有六个子字符串 ("z", "a", "b", "za", "ab", and "zab") 在 base 中出现。
思路:

可以使用线性dp来做。这里要注意的是dp[i],表示的是以这个字母为结尾对该答案的贡献值。说白了就是加上这个字母之后,增加了多少种可能的机会。

动规五部曲:

dp[i]:上面

递推式:当上一个字母和下一个字母可以连上,j++;并且只有在不连的时候才会置为1;(如果出现这种a,b,c 那么j就会变成3) dp[i]=Math.max(dp[i],j);

初始化:dp[ch[0]-''a]=1;

遍历顺序:从1开始到s.length()

代码:
class Solution {
    public int findSubstringInWraproundString(String s) {
        char[] cs=s.toCharArray();
        int n=cs.length;
        int[] dp=new int[26];
        dp[cs[0]-'a']=1;
        for(int i=1,j=1;i<n;i++){
            if((cs[i]=='a'&&cs[i-1]=='z')||cs[i-1]+1==cs[i])j++;
            else j=1;
            dp[cs[i]-'a']=Math.max(dp[cs[i]-'a'],j);
        }
        int sum=0;
        for(int i=0;i<26;i++){
            sum+=dp[i];
        }
        return sum;
    }
}

二、最优除法

题意:

给定一正整数数组 numsnums 中的相邻整数将进行浮点除法。

  • 例如,nums = [2,3,4],我们将求表达式的值 "2/3/4"

但是,你可以在任意位置添加任意数目的括号,来改变算数的优先级。你需要找出怎么添加括号,以便计算后的表达式的值为最大值。

思路:

要想使表达式的值为最大值。

1.要么使分子变大,要么使分母变小。

2.这道题中每一个元素都是>=2的正整数,所以只能使分母变小

3.如何使分母变小:只能不断地将分母除以下一个数 类似于这样1/(2/3/4/5/6);

4.但是要注意一些冗余的符号。比如说只有两个元素的时候 就不需要加()

代码:
class Solution {
    public String optimalDivision(int[] nums) {
        int size=nums.length;
        StringBuilder sb=new StringBuilder();
        if(size==1)return nums[0]+"";
        if(size==2)return nums[0]+"/"+nums[1];
        for(int i=0;i<nums.length;i++){
            if(i==0)sb.append(nums[0]).append("/(");
            else if(i==nums.length-1)sb.append(nums[i]).append(")");
            else{
                sb.append(nums[i]).append("/");
            }
        }
        return sb.toString();
    }
}

三、复数乘法(简单)

注意:

在String.split()方法中,可以使用正则表达式。eg:在这道题中 a+bi;

String.split("\\ + | i ");\\是转义字符,|代表或的意思。这个表示:将字符串a+bi分解成两个部分a.b;

代码:
/**
 * i2是-1
 * 分步骤 1.实部*实部 虚部*虚部 这个是看有没有实数
 * 2.实部1*虚部2+实部2*虚部1 这个是i前面的系数
 */
class Solution {
    public String complexNumberMultiply(String num1, String num2) {
        String[] split1=num1.split("\\+|i");
        String[] split2=num2.split("\\+|i");
        //先计算实数
        int number1=Integer.parseInt(split1[0]);//实数1
        int number2=Integer.parseInt(split2[0]);//实数2
        int number3=Integer.parseInt(split1[1]);//虚部实数1
        int number4=Integer.parseInt(split2[1]);//虚部实数2

        System.out.println("实数1:"+number1 +"虚数1:"+number3+"实数2:"+number2+"虚数2:"+number4);
 
        
        StringBuilder sb=new StringBuilder();
        int real=number1*number2-number3*number4;
        int virtual=number1*number4+number2*number3;
        sb.append(real).append("+").append(virtual).append("i");
        return sb.toString();
    }
}

四、外观数列(一般)

输入:n = 4

输出:"1211"

解释:

countAndSay(1) = "1"

countAndSay(2) = "1" 的行程长度编码 = "11"

countAndSay(3) = "11" 的行程长度编码 = "21"

countAndSay(4) = "21" 的行程长度编码 = "1211"

n是变换的次数(从普通数字变成行程长度编码)

eg:1->11(1个1);11->21(2个1)  21->1211(1个2 1个1)...

思路:

从给出的字符串中我们需要进行判断,连续相同的数字有几个,然后把数字记录下来。如何判断连续相同的数字(nums[i]==nums[i+1]&&i+1<nums.length)

代码:
class Solution {
    public String countAndSay(int n) {
        String str = "1";
        for (int i = 1; i < n; i++) {
            str = encode(str);
            System.out.println(str);
        }
        return str;
    }

    // 从原始字符串->行程长度编码
    public String encode(String str) {
        int count = 1;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            if (i < str.length() - 1 && str.charAt(i) == str.charAt(i + 1)) {
                count++;
            }else{
                sb.append(count).append(str.charAt(i));
                count=1;
            }
        }
        return sb.toString();
    }

    // 从行程长度编码->到原始字符串
    public String decode(String str) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.length() - 1; i += 2) {
            Integer count = str.charAt(i) - '0';
            for (int j = 0; j < count; j++) {
                sb.append(str.charAt(i + 1));
            }
        }
        return sb.toString();
    }
}

五、整数转罗马数字(模拟)

思路:

将罗马数字可以组成的大小(从大到小)放到一个数组里面,然后字符串表示放到一个数组里面。然后按照从大到小进行对值抽离。

int[] arr=new int[]{1000,900,500,400,100,90,50,40,10,9,5,4,1};

eg 1994:1000(遍历) num-=value 还剩900(遍历) num-=value 还剩4(继续遍历) 然后num-=value。这样的话根据字符串数组里面对应的,使用StringBuilder sb拼接就行。

代码:
class Solution {
    public String intToRoman(int num) {
        int[] arr=new int[]{1000,900,500,400,100,90,50,40,10,9,5,4,1};
        String[] strs=new String[]{"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
        StringBuilder sb=new StringBuilder();
        for(int i=0;i<arr.length&&num>0;i++){
            int value=arr[i];
            String str=strs[i];
            while(num>=value){
                num-=value;
                sb.append(str);
            }
        }
        return sb.toString();
    }
}

六、字符串转换整数(值的越界处理)

规则:

1.当遇到前置空格的时候,不用管,直接跳过

2.前置空格后会遇到‘+’,‘-’。如果是+就是正数,如果是-就是负数

3.如果后面出现的不是数字 直接返回已经出现过的数字

eg:   +45aaa :返回45  eg:-4aa2 返回-4

注意:可能会遇到越界的问题(如何处理)

每当result=result*10+digit的时候,要对result进行判断。

if(result>(Integer.MAX_VALUE)/10||

result==(Integer.MAX_VALUE)/10&&digit<Integer.MAX_VALUE%10)

如果遇到这种情况就越界了。result*10+digit>Integer.MAX_VALUE;

代码:
class Solution {
    public int myAtoi(String s) {
        int size=s.length();
        if (s == null || size == 0) {
            return 0;
        }

        int i = 0;//指针
        int sign = 1;//判断正负
        int result = 0;//返回的结果

        // 丢弃前导空格
        while(i<size&&s.charAt(i)==' ')i++;
        // 判断符号
        if(i<size&&(s.charAt(i)=='+'||s.charAt(i)=='-')){
            if(s.charAt(i)=='-')sign=-1;
            i++;
        }
        // 转换数字
        while(i<size&&Character.isDigit(s.charAt(i))){
            //Character.isDigit(ch) 判断字符是否是数字的方法
            int digit=s.charAt(i)-'0';
            //防止溢出
            if(result>(Integer.MAX_VALUE-digit)/10){
                //出现这两种情况就有问题
                return sign==1?Integer.MAX_VALUE:Integer.MIN_VALUE;
            }
            result=result*10+digit;
            i++;
        }
        return result*sign;
    }
}

七、压缩字符串(处理技巧)

从一个空字符串 s 开始。对于 chars 中的每组 连续重复字符 :

  • 如果这一组长度为 1 ,则将字符追加到 s 中。
  • 否则,需要向 s 追加字符,后跟这一组的长度。

压缩后得到的字符串 s 不应该直接返回 ,需要转储到字符数组 chars 中。需要注意的是,如果组长度为 10 或 10 以上,则在 chars 数组中会被拆分为多个字符。

题意:

对字符数组中的字符进行判断,如果只出现一次,只需要把字符添加到chars数组中;

如果出现了多次,就要把字符和次数都添加到chars数组中。aaaaaaaaaaaa12次。要添加‘a’,'1','2'

思路:

指针法:依然是统计连续相同的字符。但是不需要考虑i<length-1什么的

使用char ch=chars[index]记录初始的字符。然后挨个比较就行

代码:
class Solution {
    public int compress(char[] chars) {
        int size = chars.length;
        int index = 0;
        int cnt = 0;
        while (index < size) {
            char currentChar=chars[index];
            int count=0;
            //找连续相同的字母数量
            while (index<size&&chars[index]==currentChar) {
                count++;
                index++;
            }
            chars[cnt++]=currentChar;
            if (count >1){
                String countStr=String.valueOf(count);
                for(char c:countStr.toCharArray()){
                    chars[cnt++]=c;
                }
            }
        }
        return cnt;
    }
}

八、比较版本号(如何把情况综合在一起考虑?)

给你两个 版本号字符串 version1 和 version2 ,请你比较它们。版本号由被点 '.' 分开的修订号组成。修订号的值 是它 转换为整数 并忽略前导零

比较版本号时,请按 从左到右的顺序 依次比较它们的修订号。如果其中一个版本字符串的修订号较少,则将缺失的修订号视为 0

输入:version1 = "1.0", version2 = "1.0.0.0"

输出:0

version1 有更少的修订号,每个缺失的修订号按 "0" 处理。

思路:

使用String的split方法(注意这里要加转义字符\\),字符串可能是没有.的,因此可能出现某一个版本字符串split后的长度为0;

所以在进行for循环的时候for(int i=0;i<ver1.length||i<ver2.length;i++)

if(x<ver1.length) or if(y<ver2.length) 如果长度为0的话,那么就是0;

如果两个字符串都带有"."。那么直接分割就行,然后对比每一个. .之间的大小,Integer.parseInt(ver1[i])已经是去掉前置0的情况了。直接比较就行

代码:
class Solution {
    public int compareVersion(String version1, String version2) {
        String[] split1 = version1.split("\\.");
        String[] split2 = version2.split("\\.");
        for (int i = 0; i < split1.length || i < split2.length; i++) {
            int x = 0, y = 0;
            if (i < split1.length) {
                x = Integer.parseInt(split1[i]);
            }
            if (i < split2.length) {
                y = Integer.parseInt(split2[i]);
            }
            if (x < y)
                return -1;
            if (x > y)
                return 1;
        }
        return 0;
    }
}

九、罗马数字转整数

思路:

首先使用 map集合将罗马数字和数值联系在一起。然后根据所给的字符串进行判断,如果charAt(i)所对应的数值是小于charAt(i+1)的,这说明是两个字母组在一起表示的。那么这种情况就要把当前字母所表示的数值减去。

对比整数转罗马数字:
思路:整数转罗马数字是将所有表示数值的罗马字符从大到小都组合起来,然后根据一个一个试,如果当时罗马字符<number的。那么就while循环 --到>number。然后再用下一个字符试。
代码:
class Solution {
    Map<Character, Integer> values = new HashMap<Character, Integer>() {{
        put('I', 1);put('V', 5);put('X', 10); put('L', 50);
         put('C', 100); put('D', 500);put('M', 1000);
    }};

    public int romanToInt(String s) {
        int value=0;
        int n = s.length();
        for(int i=0;i<n;i++){
            int preValue=values.get(s.charAt(i));
            if(i+1<n&&values.get(s.charAt(i+1))>preValue){
                value-=preValue;
            }else{
                value+=preValue;
            }
        }
        return value;
    }
}

相关推荐

  1. 算法学习day18字符串

    2024-07-21 00:30:04       14 阅读
  2. 算法训练day10字符串总结双指针回顾

    2024-07-21 00:30:04       51 阅读
  3. 算法打卡day18

    2024-07-21 00:30:04       36 阅读
  4. 算法日记day 13(删除字符串中的所有重复元素)

    2024-07-21 00:30:04       19 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-21 00:30:04       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-21 00:30:04       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-21 00:30:04       45 阅读
  4. Python语言-面向对象

    2024-07-21 00:30:04       55 阅读

热门阅读

  1. 【总结】计组第三章大局观:访存相关

    2024-07-21 00:30:04       14 阅读
  2. 数据结构的分类

    2024-07-21 00:30:04       15 阅读
  3. 数据仓库事实表

    2024-07-21 00:30:04       16 阅读
  4. [运算符重载 - 取地址运算符 - const 成员函数]

    2024-07-21 00:30:04       17 阅读
  5. Python print() 格式化输出

    2024-07-21 00:30:04       22 阅读
  6. Web学习day05

    2024-07-21 00:30:04       20 阅读
  7. 高阶面试-hw算法整理

    2024-07-21 00:30:04       19 阅读
  8. std::bind 简单实验

    2024-07-21 00:30:04       17 阅读
  9. 中电金信:语言服务游戏行业解决方案

    2024-07-21 00:30:04       17 阅读
  10. 数据库之数据类型

    2024-07-21 00:30:04       15 阅读