1.打印从1到最大的n位数
输入数字 n
,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
输入: n = 1 输出: [1,2,3,4,5,6,7,8,9]
分析:
1)int最大用32位字节表示,本题没有说明n的范围,所以极可能超出int数组的范围,所以转化为字符输出。
2)生成数字的字符串集:当输入为n时,想当于n位上0-9的全排列,先确定最高位,后面的n-1位全排列。
3)上面的全排列存在两个问题
- 数一开始是从0开始的
- 数的高位有多余的0;这时需要利用字符的截取(是因为当进行递归时,产生的字符的数组,通过方法将数组转化为字符串),获得不含高位是0的数;当每次递归遇到9时,就会产生进位,此时高位就少一个0;所以用nine从0开始统计9的数量,start是从数组的第n-1位开始截取的。当n-nine ==start,此时,start--,使截取字符数量减少。
- 下面的nine--;不太明白;但是举例n=2可以理解,当个位第一次出现9时加
class Solution {
//根据n确定一个数的对应字符的长度-》对应的字符数组
char[] num;
StringBuffer res;//定义结果
int n,start,nine;//数组长度;截取字符的下标;9的数量
char[] loop ={'0','1','2','3','4','5','6','7','8','9'};//用于递归的字符串
public int[] printNumbers(int n) {
//初始化属性
this.n = n;
res = new StringBuffer();
start = n-1;
nine =0;
num = new char[n];
df(0);//从最高位索引位置开始递归
res.deleteCharAt(res.length()-1);//删除最后一个逗号
return res.toString;
}
//递归开始,没有返回值,因为res在类属性中定义可以直接用
void dfs(int x){
//退出方法的条件
if(x==n){
//此时说明字符数组索引为n-1的已经安排好了
//所以此时,x是从0开始的
string s = String.valueOf(num).subString(start);
if(!s.equals("0")) res.append(s+’,);//这里字符串重写了方法,就判断两个值是否相等
if(n-nine == start) start--;
return;
}
//一位位递归
//这里递归完一位数才会执行下面的nine--;
for(char i :loop){
num[x] = i;//高位的值确定了,所以要递归数组确定下一位
dfs(x+1);//比如上面是确定num[0],这个递归确定num[1],从0到9字符中选择
//当i每次递归到9时,说明后面的值要进位,但当这个循环结束时,把nine恢复到原来的值
if(i=='9') nine++;
}
nine--;//在回溯前让nine恢复到之前的状态
}
}
2.输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
题目链接:力扣
class Solution {
char[] chars;
List<String> res = new ArrayList<>();
public String[] permutation(String s) {
chars = s.toCharArray();
dfs(0);
return res.toArray(new String[res.size()]);
}
//x是要固定的元素索引
void dfs(int x){
//回溯条件:x递归到最后一个元素时;因为交换是影响的两个元素,所以此时,x是长度减一
if(x==chars.length-1) {
//将字符数组转为字符串
res.add(String.valueOf(chars));
return;
}
HashSet<Character> s = new HashSet<>();
for(int i=x;i<chars.length;i++){
//将这位上的元素加入set,当有重复元素时方便剪枝
if(s.contains(chars[i])) continue;
s.add(chars[i]);
swap(i,x);//固定第x位的元素
dfs(x+1);//固定第x+1位元素
swap(x,i);//恢复位置,等进入for循环确保顺序不变
}
}
void swap(int i,int j){
char tem= chars[i];
chars[i]=chars[j];
chars[j]=tem;
}
}
3.现在有一个只包含数字的字符串,将该字符串转化成IP地址的形式,返回所有可能的情况。
例如:
给出的字符串为"25525522135",
返回["255.255.22.135", "255.255.221.35"]. (顺序没有关系)
数据范围:字符串长度
要求:空间复杂度 0(n),时间复杂度 o(n)
注意:ip地址是由四段数字组成的数字序列,格式如 "x.x.x.x",其中 x 的范围应当是 [0,255]。
题目链接:力扣
方法一:隔板法(确定三个隔板存放的位置,之后在进行筛选合适的位置)
class Solution {
List<String> res = new ArrayList<>();
public List<String> restoreIpAddresses(String s) {
//暴力:先一位位确定,当长度正好是12时,加入数组中
//判断条件直接不符的情况(4,12)
if(s == null || s.length()<4 || s.length()>12){
return res;
}
//隔板法确定板的所有位置,在进行筛选
int len = s.length();
//这里substring,截取包括前面元素,不包括后面元素
for(int i =1;i<len-2;i++){//第一块板的活动位置,最后三个位置不能取(三个值有两个空),留给剩余两个板
for(int j =i+1;j<len-1;j++){//第二个板,不能取最后两个位置(还有一个空,)留给最后一个板
for(int n =j+1;n<len;n++){
//对各个隔板的情况检查
if(check(s,i,j,n)){
StringBuffer r = new StringBuffer();
r.append(s.substring(0,i)+".");
r.append(s.substring(i,j)+".");
r.append(s.substring(j,n)+".");
r.append(s.substring(n));
res.add(r.toString());
}
}
}
}
return res;
}
public boolean check(String s,int i,int j,int m){
String a = s.substring(0,i);
//判断截取的值是否在0-255之间
if(a.length()>1 && a.charAt(0) =='0' || Integer.parseInt(a)>255){
return false;
}
String b = s.substring(i,j);
if(b.length()>1 && b.charAt(0) =='0' || Integer.parseInt(b)>255){
return false;
}
String c = s.substring(j,m);
if(c.length()>1 && c.charAt(0) =='0' || Integer.parseInt(c)>255){
return false;
}
String d = s.substring(m);
if(d.length()>1 && d.charAt(0) =='0' || Integer.parseInt(d)>255){
return false;
}
return true;
}
}
方法二:回溯
class Solution {
List<String> res = new ArrayList<>();
public List<String> restoreIpAddresses(String s) {
if (s.length() < 4 || s.length() > 12) {
return new ArrayList<>();
}
String str = "";
dfs(s,4,0,str);
return res;
}
public void dfs(String s,int cnt,int i,String str) {
if (cnt == 0 && i == s.length()) {
// 去掉最后一个'.'位置
res.add(str.substring(0,str.length() - 1));
return;
}
for (int step=1;step<=3;++step){
// 条件判断
/**
1.如果当前网段长度大于1 但是前缀为0,则这个位置不可用
2.如果当前索引大于字符串长度,且仍处于递归过程中,表示不可用
3.如果当前网断的长度为3,但是大于255 则网段非法 不可用
*/
if ((step!=1 && s.charAt(i) == '0') || (step+i>s.length()) || (step==3&&s.substring(i,i+step).compareTo("255")>0)) return;
dfs(s,cnt-1,i+step,str+s.substring(i,i+step) + ".");
}
}
}