NC刷题笔记7-字符串

NC刷题笔记7-字符串

    • NC1 大数加法
    • NC10 大数乘法
    • NC17 最长回文子串
    • NC20 数字字符串转化成IP地址
    • BM83 字符串变形
    • BM84 最长公共前缀
    • BM85 验证IP地址
    • BM86 大数加法

本博客文章(学习笔记)导航 (点击这里访问)
在这里插入图片描述

NC1 大数加法

描述
以字符串的形式读入两个数字,编写一个函数计算它们的和,以字符串形式返回。

数据范围:len(s),len(t),len(s),len(t)≤100000,字符串仅由'0'~‘9’构成
要求:时间复杂度 O(n)

示例1
输入:"1","99"
返回值:"100"
说明:1+99=100     

示例2
输入:"114514",""
返回值:"114514"
思路:
	合并数组
import java.util.  ;


public class Solution {
    /    
        代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
        计算两个数之和
        @param s string字符串 表示第一个整数
        @param t string字符串 表示第二个整数
        @return string字符串
       /
    public String solve (String s, String t) {
        // write code here
        int sLength=s.length();
        int tLength=t.length();
        int minLength=Math.min(sLength,tLength);
        s=reverse(s);
        t=reverse(t);
        StringBuilder sb=new StringBuilder();
        int addNum=0;
        for(int i=0;i<minLength;i++){
            int sNum=(int)(s.charAt(i)-'0');
            int tNum=(int)(t.charAt(i)-'0');
            int nummy=sNum+tNum+addNum;
            addNum=(int)(nummy/10);
            sb.append(nummy%10+"");
        }
        if(sLength>minLength){
            for(int i=minLength;i<sLength;i++){
                int sNum=(int)(s.charAt(i)-'0');
                int nummy=sNum+addNum;
                addNum=(int)(nummy/10);
                sb.append(nummy%10+"");
            }
        }
        if(tLength>minLength){
            for(int i=minLength;i<tLength;i++){
                int sNum=(int)(t.charAt(i)-'0');
                int nummy=sNum+addNum;
                addNum=(int)(nummy/10);
                sb.append(nummy%10+"");
            }
        }
        if(addNum!=0) sb.append(addNum+"");
        sb=sb.reverse();
        String res=sb.toString();
        for(int i=0;i<res.length();i++){
            if(res.charAt(i)!='0') return res.substring(i,res.length());
        }
        return res;
    }
    
    public String reverse(String str){
        return new StringBuilder(str).reverse().toString();
    }
}

NC10 大数乘法

描述
以字符串的形式读入两个数字,编写一个函数计算它们的乘积,以字符串形式返回。
数据范围: 读入的数字大小满足0≤n≤10^1000
要求:空间复杂度 O(n),时间复杂度 O(n^2)
示例1  输入:"11","99"  返回值:"1089"  说明:11  99=1089 
示例2  输入:"1","0"  返回值:"0"
import java.util.  ;
public class Solution {
    public String solve (String s, String t) {
        String res="0";
        for(int i=0;i<t.length();i++){
            char c=t.charAt(i);
            int n=t.length()-1-i;
            String temp=twoNummultiply(s,c,n);
            res=twoNumsum(res,temp);
        }
        return res;
    }
    
    public String twoNummultiply(String s,char c,int n){
        if(c=='0') return "0";
        int mulNum=(int)(c-'0');
        StringBuilder sb=new StringBuilder();
        int addNum=0;
        for(int i=s.length()-1;i>=0;i--){
            int sNum=(int)(s.charAt(i)-'0');
            int temp=sNum  mulNum+addNum;
            addNum=(int)(temp/10);
            sb.append(temp%10);
        }
        if(addNum!=0) sb.append(addNum);
        sb=sb.reverse();
        while(n>0){
            sb.append("0");
            n--;
        }
        return sb.toString();
    }
    
    public String twoNumsum(String s,String t){
        int sLength=s.length();
        int tLength=t.length();
        int minLength=Math.min(sLength,tLength);
        s=reverse(s);
        t=reverse(t);
        StringBuilder sb=new StringBuilder();
        int addNum=0;
        for(int i=0;i<minLength;i++){
            int sNum=(int)(s.charAt(i)-'0');
            int tNum=(int)(t.charAt(i)-'0');
            int nummy=sNum+tNum+addNum;
            addNum=(int)(nummy/10);
            sb.append(nummy%10+"");
        }
        if(sLength>minLength){
            for(int i=minLength;i<sLength;i++){
                int sNum=(int)(s.charAt(i)-'0');
                int nummy=sNum+addNum;
                addNum=(int)(nummy/10);
                sb.append(nummy%10+"");
            }
        }
        if(tLength>minLength){
            for(int i=minLength;i<tLength;i++){
                int sNum=(int)(t.charAt(i)-'0');
                int nummy=sNum+addNum;
                addNum=(int)(nummy/10);
                sb.append(nummy%10+"");
            }
        }
        if(addNum!=0) sb.append(addNum+"");
        sb=sb.reverse();
        String res=sb.toString();
        for(int i=0;i<res.length();i++){
            if(res.charAt(i)!='0') return res.substring(i,res.length());
        }
        return res;
    }
    
    public String reverse(String str){
        return new StringBuilder(str).reverse().toString();
    }
}

NC17 最长回文子串

描述
对于长度为n的一个字符串A(仅包含数字,大小写英文字母),请设计一个高效算法,计算其中最长回文子串的长度。
数据范围:1≤n≤1000
要求:空间复杂度 O(1),时间复杂度 O(n^2)
进阶:  空间复杂度 O(n),时间复杂度 O(n)

示例1 输入:"ababc"  返回值:3
说明:最长的回文子串为"aba"与"bab",长度都为3
示例2 输入:"abbba"  返回值:5
示例3  输入:"b" 返回值:1
思路1:
	两层for循环,依次判断i和j之间是不是回文
思路2:
	中心扩散法(奇数和偶数)
import java.util.  ;

public class Solution {
    public int getLongestPalindrome(String A) {
        // write code here
        char[] chars=A.toCharArray();
        int maxlength=0;
        for(int i=0;i<chars.length;i++){
            for(int j=i;j<chars.length;j++){
                if(judge(i,j,chars)) maxlength=Math.max(maxlength,j-i+1);
            }
        }
        return maxlength;
    }
    
    public boolean judge(int i,int j,char[] chars){
        if(i==j) return true;
        while(i<j){
            if(chars[i]!=chars[j]) return false;
            i++;
            j--;
        }
        return true;
    }
}
import java.util.  ;
public class Solution {
    public int getLongestPalindrome (String A) {
        // write code here
        if(A.length()==0||A.length()==1) return A.length();
        int res=1;
        for(int i=0;i<A.length();i++){
            res=Math.max(res,Longest(i,A));
        }
        return res;
    }
    
    public int Longest(int i,String A){
        //奇数
        int left=i,right=i,res=1;
        while(left>=0&&right<A.length()){
            if(A.charAt(left)==A.charAt(right)){
                res=Math.max(right-left+1,res);
                left--;
                right++;
            }else{
                break;
            }
        }
        //偶数
       if((i+1)<A.length() && A.charAt(i+1)==A.charAt(i)){
           left=i-1;
           right=i+2;
           res=Math.max(2,res);
           while(left>=0&&right<A.length()){
                if(A.charAt(left)==A.charAt(right)){
                    res=Math.max(right-left+1,res);
                    left--;
                    right++;
                }else{
                    break;
                }
           }
       }
       return res;
    }
}

NC20 数字字符串转化成IP地址

描述
现在有一个只包含数字的字符串,将该字符串转化成IP地址的形式,返回所有可能的情况。
例如:给出的字符串为"25525522135",
返回["255.255.22.135", "255.255.221.35"]. (顺序没有关系)
数据范围:字符串长度0≤n≤12
要求:空间复杂度 O(n!),时间复杂度 O(n!)
注意:ip地址是由四段数字组成的数字序列,格式如 "x.x.x.x",其中 x 的范围应当是 [0,255]。

示例1
输入:"25525522135"
返回值:["255.255.22.135","255.255.221.35"]

示例2
输入:"1111"
返回值:["1.1.1.1"]

示例3
输入:"000256"
返回值:"[]"
思路1:
	暴力枚举,每一个位包含一到三位字符
	如果四个位置相加为s.length

思路2:
	递归回溯
import java.util.  ;
public class Solution {
    public ArrayList<String> restoreIpAddresses (String s) {
        ArrayList<String> list = new ArrayList();
        for(int a=1; a<4; a++){
            for(int b=1; b<4; b++){
                for(int c=1; c<4; c++){
                    for(int d=1; d<4; d++){
                        if(a+b+c+d==s.length()){
                            String s1 = s.substring(0, a);
                            String s2 = s.substring(a, a+b);
                            String s3 = s.substring(a+b, a+b+c);
                            String s4 = s.substring(a+b+c, a+b+c+d);
                            if(check(s1)&&check(s2)&&check(s3)&&check(s4)){
                                String ip = s1+"."+s2+"."+s3+"."+s4;
                                list.add(ip);
                            }
                        }
                    }
                }
            }
        }
        return list;
    }
    
    public boolean check(String s){
        if(Integer.valueOf(s)<=255){
            if(s.charAt(0)!='0' || s.charAt(0)=='0'&&s.length()==1) 
                return true;
        }
        return false;
    }
}
思路2import java.util.  ;
public class Solution {
    public ArrayList<String> restoreIpAddresses (String s) {
        if (s.length() > 12) {
            return null;
        }
        StringBuilder sb = new StringBuilder(s);
        doRestoreIpAddresses(sb, 1);
        return ans;
    }
    ArrayList<String> ans = new ArrayList<>();
    public void doRestoreIpAddresses(StringBuilder s, int m) { // 回溯暴力算法,还要很多地方没有剪枝
        String[] nums = s.toString().split("\\.");
        if (nums.length > 4) { // 剪枝
            return;
        }
        if (validateIPv4(s.toString())) { // 结束条件
            ans.add(String.copyValueOf(s.toString().toCharArray()));
            return;
        }

        for (int i = m; i < s.length(); i++) { // 回溯
            s.insert(i, "."); 
            doRestoreIpAddresses(s, i + 2);
            s.replace(i, i + 1, "");

        }
    }
    
     public boolean validateIPv4(String IP) {
        String[] nums = IP.split("\\.");
        if (nums.length !=  4) {
            return false;
        }
        for (String x : nums) {
            // 0-255:
            if (x.length() == 0 || x.length() > 3) return false;
            // 0的情况
            if (x.charAt(0) == '0' && x.length() != 1) return false;
            // 大于255
            if (Integer.parseInt(x) > 255) return false;
        }
        return true;
    }
}

BM83 字符串变形

描述
对于一个长度为 n 字符串,我们需要对它做一些变形。
首先这个字符串中包含着一些空格,就像"Hello World"一样,然后我们要做的是把这个字符串中由空格隔开的单词反序,同时反转每个字符的大小写。
比如"Hello World"变形后就变成了"wORLD hELLO"。
数据范围: 1≤n≤10^6, 字符串中包括大写英文字母、小写英文字母、空格。
进阶:空间复杂度 O(n), 时间复杂度 O(n)

输入描述:给定一个字符串s以及它的长度n(1 ≤ n ≤ 10^6)
返回值描述:请返回变形后的字符串。题目保证给定的字符串均由大小写字母和空格构成。

示例1
输入:"This is a sample",16
返回值:"SAMPLE A IS tHIS"

示例2
输入:"nowcoder",8
返回值:"NOWCODER"
思路:
	1 用StringBuilder和Stack来做
	2 遇到空格就把 StringBuilder的东西入栈并清空StringBuilder
	3 遇到其他字符就放在StringBuilder中
	4 最后把栈里的元素弹出来,后面拼空格
	5 再把最后一个空格删掉
import java.util.  ;

public class Solution {
    public String trans(String s, int n) {
        // write code here
        //使用栈的特性,输出为反向
        Stack<String>stack=new Stack<>();
        StringBuffer buffer=new StringBuffer();
        for(int i=0;i<n;i++){
            //遇到空格入栈
            if(s.charAt(i)==' '){
                stack.push(buffer.toString());
                buffer.delete(0,buffer.length());
            }else{
                //小写字母-32转为大写
                if(s.charAt(i)>='a'&&s.charAt(i)<='z'){
                    buffer.append((char)(s.charAt(i)-32));
                }else{
                    //大写字母+32转为小写
                    buffer.append((char)(s.charAt(i)+32));
                }
            }
        }
        //最后一个单词入栈
        stack.push(buffer.toString());
        StringBuffer ans=new StringBuffer();
        while(!stack.isEmpty()){
            ans.append(stack.pop());
            //每个单词后接空格
            ans.append(' ');
        }
        //删除最后一个多余空格
        ans.deleteCharAt(ans.length()-1);
        return ans.toString();
    }
}

BM84 最长公共前缀

描述
给你一个大小为 n 的字符串数组 strs ,其中包含n个字符串 , 编写一个函数来查找字符串数组中的最长公共前缀,返回这个公共前缀。数据范围:0≤n≤5000, 0≤len(strs i)≤5000
进阶:空间复杂度 O(n),时间复杂度 O(n)

示例1
输入:["abca","abc","abca","abc","abcc"]
返回值:"abc"

示例2
输入:["abc"]
返回值:"abc"
思路:
	1 先按照字典序排序
	2 比较第一个和最后一个的公共前缀
import java.util.  ;
public class Solution {
    public String longestCommonPrefix (String[] strs) {
        if(strs==null||strs.length==0) return "";
        Arrays.sort(strs);
        StringBuilder sb=new StringBuilder();
        for(int i=0;i<strs[0].length();i++){
            if(strs[0].charAt(i)==strs[strs.length-1].charAt(i)){
                sb.append(strs[0].charAt(i));
            }else{
                break;
            }
        }
        return sb.toString();
    }
}

BM85 验证IP地址

描述
编写一个函数来验证输入的字符串是否是有效的 IPv4 或 IPv6 地址
IPv4 地址由十进制数和点来表示,每个地址包含4个十进制数,其范围为 0 - 255, 用(".")分割。比如,172.16.254.1;
同时,IPv4 地址内的数不会以 0 开头。比如,地址 172.16.254.01 是不合法的。

IPv6 地址由8组16进制的数字来表示,每组表示 16 比特。这些组数字通过 (":")分割。比如,  2001:0db8:85a3:0000:0000:8a2e:0370:7334 是一个有效的地址。而且,我们可以加入一些以 0 开头的数字,字母可以使用大写,也可以是小写。所以, 2001:db8:85a3:0:0:8A2E:0370:7334 也是一个有效的 IPv6 address地址 (即,忽略 0 开头,忽略大小写)。

然而,我们不能因为某个组的值为 0,而使用一个空的组,以至于出现 (::) 的情况。 比如, 2001:0db8:85a3::8A2E:0370:7334 是无效的 IPv6 地址。
同时,在 IPv6 地址中,多余的 0 也是不被允许的。比如, 02001:0db8:85a3:0000:0000:8a2e:0370:7334 是无效的。

说明: 你可以认为给定的字符串里没有空格或者其他特殊字符。
数据范围:字符串长度满足5≤n≤50
进阶:空间复杂度 O(n),时间复杂度 O(n)

示例1
输入:"172.16.254.1"
返回值:"IPv4"
说明:这是一个有效的 IPv4 地址, 所以返回 "IPv4" 

示例2
输入:"2001:0db8:85a3:0:0:8A2E:0370:7334"
返回值:"IPv6"
说明:这是一个有效的 IPv6 地址, 所以返回 "IPv6" 

示例3
输入:"256.256.256.256"
返回值:"Neither"
说明:这个地址既不是 IPv4 也不是 IPv6 地址
注意事项
	2 分割字符串时,使用limit = -1的split函数,使得字符串末尾或开头有一个'.'或':'也能分割出空的字符串
	2 使用Integer.parseInt()函数检查异常
	3 startsWith("0")方法判断以"0"为开头
import java.util.  ;
public class Solution {
    public String solve(String IP) {
        return validIPv4(IP) ? "IPv4" : (validIPv6(IP) ? "IPv6" : "Neither");
    }

    private boolean validIPv4(String IP) {
        String[] strs = IP.split("\\.", -1);
        if (strs.length != 4) {
            return false;
        }

        for (String str : strs) {
            if (str.length() > 1 && str.startsWith("0")) {
                return false;
            }
            try {
                int val = Integer.parseInt(str);
                if (!(val >= 0 && val <= 255)) {
                    return false;
                }
            } catch (NumberFormatException numberFormatException) {
                return false;
            }
        }
        return true;
    }

    private boolean validIPv6(String IP) {
        String[] strs = IP.split(":", -1);
        if (strs.length != 8) {
            return false;
        }

        for (String str : strs) {
            if (str.length() > 4 || str.length() == 0) {
                return false;
            }
            try {
                int val = Integer.parseInt(str, 16);
            } catch (NumberFormatException numberFormatException) {
                return false;
            }
        }
        return true;
    }
}

BM86 大数加法

描述
以字符串的形式读入两个数字,编写一个函数计算它们的和,以字符串形式返回。数据范围:len(s),len(t)≤100000,字符串仅由'0'~‘9’构成
要求:时间复杂度 O(n)

示例1
输入:"1","99"
返回值:"100"
说明:1+99=100      

示例2
输入:"114514",""
返回值:"114514"
思路:
	合并链表的类似做法
	1 反转两条字符串
	2 合并字符串
	3 反转结果
import java.util.  ;

public class Solution {
    public String solve (String s, String t) {
        StringBuilder s0=new StringBuilder(s);
        StringBuilder t0=new StringBuilder(t);
        s=s0.reverse().toString();
        t=t0.reverse().toString();
        int add=0,i=0,j=0;
        StringBuilder res=new StringBuilder();
        while(i<s.length()&&j<t.length()){
            int sum=(int)(s.charAt(i)-'0')+(int)(t.charAt(j)-'0')+add;
            res.append(sum%10+"");
            add=sum/10;
            i++;
            j++;
        }
        
        while(i<s.length()){
            int sum=(int)(s.charAt(i)-'0')+add;
            res.append(sum%10+"");
            add=sum/10;
            i++;
        }
        
        while(j<t.length()){
            int sum=(int)(t.charAt(j)-'0')+add;
            res.append(sum%10+"");
            add=sum/10;
            j++;
        }
        
        if(add!=0) res.append(add+"");
        return res.reverse().toString();
    }
}

你可能感兴趣的:(算法,数据结构)