[剑指offer]大可日常打卡-字符串

5.替换空格

    请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

public class Solution {
    public String replaceSpace(StringBuffer str) {
    	if(str==null||str.length()==0){
            return str.toString();
        }
        int len=str.length();
        StringBuffer res=new StringBuffer();
        for(int i=0;i<len;i++){
            if(str.charAt(i)!=' '){
                res.append(String.valueOf(str.charAt(i)));
                continue;
            }else{
                res.append("%20");
                continue;
            }
        }
        return res.toString();
            
    }
}

20.表示数值的字符串

    请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。

思路:先想想表示数值的字符串的特征。

A[.[B]][e|EC]     .B[e|EC]

A是整数部分,B紧跟着小数点为小数部分,C紧跟着e为指数部分。

小数里面也可以没有整数部分,所以A部分不是必须的,如果一个数没有整数部分,那么小数部分不能为空!

A和C都可能是以+或者-开头的0-9的数位串;B也是0-9的数位串,但是B前面不能有正负号。

以123.45e+6为例。

    判断一个字符串是否符合上述模式的时候,首先尽可能扫描A部分,遇到小数点就扫描B部分,遇到E|e就扫描C部分。

public class Solution {
    public static boolean isNumeric(char[] str) {
        if(str==null||str.length==0){
            return false;
        }
        int index=0;
        //首先判断有没有符号位
        if(str[index]=='+'||str[index]=='-'){
            index++;
        }
        //但是如果只有符号位也不对啊
        if(index==str.length){
            return false;
        }
        //如果不是只有符号位的话,就开始扫描数字,只要是数字,那么index往下移
        index=scanInteger(str,index);
        //整数部分扫描完以后,先看index是不是小于length,要是index小于length,那么开始扫描小数部分
        if(index<str.length){
            if(str[index]=='.'){
                //开始扫描小数部分啦
                index++;
                index=scanInteger(str,index);
                //把所有的小数扫描完以后,看index有没有超过长度,要是小于长度,再开始看指数部分!
                if(index<str.length){
                    if(str[index]=='e'||str[index]=='E'){
                        index++;
                        return isExponential(str,index);
                    }
                    return false;
                }
                return true;
            }else if(str[index]=='e'||str[index]=='E'){
                //如果没有小数部分,有指数部分
                index++;
                if(index==str.length){
                    return false;
                }
                return isExponential(str,index);
            }
            return false;
        }
        return true;
    
    }

    
    public static boolean isExponential(char[] str,int index){
        if(str[index]=='+'||str[index]=='-'){
            index++;
        }
        index=scanInteger(str,index);
        if(index==str.length){
            return true;
        }
        return false;
    }
    
    public static int scanInteger(char[] str,int index){
        while(index<str.length&&(str[index]>='0'&&str[index]<='9')){
            index++;
        }
        return index;
    }
}

38.字符串的排列

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

思路:全排列,采用递归思想。从字符串中选出一个字符当作排列的第一个字符,然后对剩余的字符进行全排列。

把一个字符分成两部分来看待,第一部分为第一个字符,第二部分为后面的所有字符,然后把结果存到一个ArrayList<String>里面。

具体过程就是先求第一个字符处于最前面的时候后面所有的全排列,然后把第一个字符挨个和后面的交换,然后递归就行了。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Set;
import java.util.HashSet;
public class Solution {
    
    public ArrayList<String> Permutation(String str) {
        ArrayList<String> res=new ArrayList<>();
        if(str==null||str.length()==0){
           return res;
        }
        char[] chars=str.toCharArray();
        PermutationHelp(chars,0,res);
        Collections.sort(res);
        return res;
    }
    public void PermutationHelp(char[] chars,int i,ArrayList<String> res){
        if(i==chars.length-1){ //到最后一个字符为递归出口
            res.add(String.valueOf(chars));
        }else{
            Set<Character> charSet=new HashSet<>();
            for(int j=i;j<chars.length;j++){
                if(j==i||!charSet.contains(chars[j])){
                    charSet.add(chars[j]);
                    swap(chars,i,j);
                    PermutationHelp(chars,i+1,res);
                    swap(chars,j,i);
                }
            }
        }
    }
    public void swap(char[] chars,int i,int j){
        char tmp=chars[i];
        chars[i]=chars[j];
        chars[j]=tmp;
    }
}

46.把数字翻译成字符串

题目:给定一个数字,按照如下规则把它翻译为字符串:0翻译成“a”,1翻译成“b”,25翻译成“z”。一个数字可能有多个翻译。例如,12258有5种不同的翻译,分别是“bccfi”、“bwfi”、“bczi”、“mcfi”、“mzi”。请实现一个函数,用来计算一个数字有多少种不同的翻译方法。

思路:以12258为例,可以分为1和2258,也可以分为12和258,然后来看2258,可以分为2和258,258子问题重复出现,所以要从下往上解决问题,就可以消除重复的子问题。从数字的末尾开始,从右到左翻译并计算不同翻译的数目。

自上而下,从最大的问题开始,递归 :
                     12258
                   /       \
              b+2258       m+258
              /   \         /   \
          bc+258 bw+58  mc+58  mz+8
          /  \      \        \     \
      bcc+58 bcz+8   bwf+8   mcf+8  mzi
        /        \       \     \
   bccf+8        bczi    bwfi   mcfi
     /
 bccfi
有很多子问题被多次计算,比如258被翻译成几种这个子问题就被计算了两次。

自下而上,动态规划,从最小的问题开始 :
f(r)表示以r为开始(r最小取0)到最右端所组成的数字能够翻译成字符串的种数。对于长度为n的数字,f(n)=0,f(n-1)=1,求f(0)。
递推公式为 f(r-2) = f(r-1)+g(r-2,r-1)*f(r);
其中,如果r-2,r-1能够翻译成字符,则g(r-2,r-1)=1,否则为0。
因此,对于12258:
f(5) = 0
f(4) = 1
f(3) = f(4)+0 = 1
f(2) = f(3)+f(4) = 2
f(1) = f(2)+f(3) = 3 
f(0) = f(1)+f(2) = 5
        public static int count(int num){
		if(num<0){
			return 0;
		}
		return getcount(String.valueOf(num));
		
	}
	public static int getcount(String num){
		int f1=1;
		int f2=1;
		int g=0;
		int tmp;
		for(int i=num.length()-2;i>=0;i--){
			if(Integer.parseInt(num.charAt(i)+""+num.charAt(i+1))<=26){
				g=1;
			}else{
				g=0;
			}
			tmp=f2;
			f2=f2+g*f1;
			f1=tmp;
		}
		return f2;
	}

48.最长不含重复字符的子字符串

题目:请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。假设字符串中只包含a-z的字符。例如,在‘arabcacfr’中,最长的不含重复子字符串是‘acfr’,长度为4。

思路:使用动态规划算法。首先定义f(i)为以第i个字符为结尾的不包含重复字符的最长长度。从左到右逐一扫描字符串中的每个字符,当计算f(i)的时候,已经知道f(i-1)了。

如果第i个字符之前没有出现过,那么f(i)=f(i-1)+1;

如果出现过,那么情况就要复杂一点,先计算第i个字符和它上次出现在字符串中的位置的距离,记为d,然后分两种情况,

(1)d>f(i-1),第i个字符上次出现在f(i-1)对应的最长子字符串之前,所以f(i)=f(i-1)+1;

(2)d<=f(i-1),第i个字符上次出现在f(i-1)对应的最长子字符串中,所以f(i)=d,同时这也意味着第i个字符出现两次所夹的子字符串中再也没有其他重复的字符了。

public class 最长的不含重复字符的子字符串 {
	public static int longestSubString(String str){
		if(str==null||str.length()==0){
			return 0;
		}
		int len=str.length();
		int maxLength=0;
		int curLength=0;
		//一个数组,存储26个字母在字符串中上一次出现的位置
		int[] position=new int[26];
		for(int i=0;i<26;i++){
			position[i]=-1; //首先把所有字母在字符串中上一次出现的位置都初始化为-1,即还没有出现过
		}
		for(int i=0;i<len;i++){ //遍历字符串的位置,从0到len-1
			int preIndex=position[str.charAt(i)-'a'];
			int distance=i-preIndex;
			if(preIndex<0||distance>curLength){ //还没出现过或者之前出现不在最长子字符串中
				
				curLength++;
			}else{ //出现过,且出现在之前的最长子字符串中
				curLength=distance; //那么当前长度就等于当前位置和上次出现位置的差值
			}
			if(curLength>maxLength){
				maxLength=curLength;
			}
			position[str.charAt(i)-'a']=i;
		}
		return maxLength;
	}
}

58.翻转字符串

题目一:翻转单词顺序

    牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?

思路:先写一个reverse函数,然后先把整个字符串reverse,然后分别把每个单词reverse。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
校园悬赏任务平台对字典管理、论坛管理、任务资讯任务资讯公告管理、接取用户管理、任务管理、任务咨询管理、任务收藏管理、任务评价管理、任务订单管理、发布用户管理、管理员管理等进行集中化处理。经过前面自己查阅的网络知识,加上自己在学校课堂上学习的知识,决定开发系统选择小程序模式这种高效率的模式完成系统功能开发。这种模式让操作员基于浏览器的方式进行网站访问,采用的主流的Java语言这种面向对象的语言进行校园悬赏任务平台程序的开发,在数据库的选择上面,选择功能强大的Mysql数据库进行数据的存放操作。校园悬赏任务平台的开发让用户查看任务信息变得容易,让管理员高效管理任务信息。 校园悬赏任务平台具有管理员角色,用户角色,这几个操作权限。 校园悬赏任务平台针对管理员设置的功能有:添加并管理各种类型信息,管理用户账户信息,管理任务信息,管理任务资讯公告信息等内容。 校园悬赏任务平台针对用户设置的功能有:查看并修改个人信息,查看任务信息,查看任务资讯公告信息等内容。 系统登录功能是程序必不可少的功能,在登录页面必填的数据有两项,一项就是账号,另一项数据就是密码,当管理员正确填写并提交这二者数据之后,管理员就可以进入系统后台功能操作区。项目管理页面提供的功能操作有:查看任务,删除任务操作,新增任务操作,修改任务操作。任务资讯公告信息管理页面提供的功能操作有:新增任务资讯公告,修改任务资讯公告,删除任务资讯公告操作。任务资讯公告类型管理页面显示所有任务资讯公告类型,在此页面既可以让管理员添加新的任务资讯公告信息类型,也能对已有的任务资讯公告类型信息执行编辑更新,失效的任务资讯公告类型信息也能让管理员快速删除。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值