版权声明:很高兴认识你,我叫邵龙飞 原创文章,转载请注明 https://blog.csdn.net/qq_37482202/article/details/85203291
有志者自有千计万计,无志者只感千难万难。
1.报数序列
/**
* 报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:
* 1. 1
* 2. 11
* 3. 21
* 4. 1211
* 5. 111221
* 1 被读作 "one 1" ("一个一") , 即 11。
* 11 被读作 "two 1s" ("两个一"), 即 21。
* 21 被读作 "one 2", "one 1" ("一个二" , "一个一") , 即 1211。
* 给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。
* 注意:整数顺序将表示为一个字符串。
*
* 示例 1:
* 输入: 1
* 输出: "1"
*
* 示例 2:
* 输入: 4
* 输出: "1211"
*/
读完题你可能有点晕,感觉这道题就想脑筋急转弯一样,不知道要求什么,其实这道题只是读起来绕口,算起来很简单,给你点提示,它的前10项是这样的
The following are the terms from n=1 to n=10 of the count-and-say sequence:
1. 1
2. 11
3. 21
4. 1211
5. 111221
6. 312211
7. 13112221
8. 1113213211
9. 31131211131221
10. 13211311123113112211
它的意思就是读出来上一组数字,第一组数字是1,第二组就是“一个一“——11,第三组就是“两个1”——21,第四组是“一个二,一个一”——121,1,第五组就是“一个一,一个二,两个一”——111221,整道题就想一个翻译器一样,解决这样的问题最容易的就是递归。
采用递归和快慢指针的方法计数,并对最后的一个数字做特殊处理
private static String method1(int n){
if (n==1) return "1";
String deel=method1(n-1);
String result="";
char aim=deel.charAt(0);
int num=0;
for (int i=0;i<deel.length();i++){
if (deel.charAt(i)!=aim){
result+=num+""+aim;
num=0;
aim=deel.charAt(i);
}
num++;
if (i==deel.length()-1){
result+=num+""+aim;
}
}
return result;
}
也可以递归加双层for循环计数
private static String method2(int n){
if (n == 1) {
return "1";
}
String input = method2(n - 1);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char currDigit = input.charAt(i);
int currTimes = 1;
for (int j = i + 1; j < input.length(); j++) {
if (currDigit == input.charAt(j)) {
currTimes++;
} else {
break;
}
}
i += currTimes - 1;
sb.append(currTimes).append(currDigit);
}
return sb.toString();
}
2.压缩数组
/**
*给定一组字符,使用原地算法将其压缩。
* 压缩后的长度必须始终小于或等于原数组长度。
* 数组的每个元素应该是长度为1 的字符(不是 int 整数类型)。
* 在完成原地修改输入数组后,返回数组的新长度。
*
* 示例 1:
* 输入:
* ["a","a","b","b","c","c","c"]
* 输出:
* 返回6,输入数组的前6个字符应该是:["a","2","b","2","c","3"]
* 说明:
* "aa"被"a2"替代。"bb"被"b2"替代。"ccc"被"c3"替代。
*
*
*1. 所有字符都有一个ASCII值在[35, 126]区间内。
*2. 1 <= len(chars) <= 1000。
*/
首先可以确定的是这道题还是要用到快慢指针,但是这里需要注意的一点便是有的字母出现的次数超过9次,这样的话就需要把该数字写到两个地方可以使用String来存取数字。
public static int method2(char[] chars) {
if (chars.length==1) return 1;
int slow=0;
char old=chars[0];
int number=0;
for (int i=0;i<=chars.length;i++){
if (i==chars.length||old!=chars[i]){
if (number==1){
if (i==chars.length){
chars[slow]=old;
slow++;
continue;
}
chars[slow]=old;
old=chars[i];
slow++;
continue;
}
String a=number+"";
chars[slow]=old;
slow++;
for(int j=0;j<a.length();j++){
chars[slow]=a.charAt(j);
slow++;
}
if (i!=chars.length){
old=chars[i];
number=1;
}
}else {
number++;
}
}
return slow;
}
上面这种写法既要考虑开头又要考虑结尾,最好还要写出现的次数,显得又臭又长,我们可以变换思维,不断比较下一位是否相同再做判断。
public static int method1(char[] chars) {
if(chars.length == 0) return 0;
int mark = 0;
int write = 0;
for(int i = 0; i < chars.length; i++){
if(i + 1 == chars.length || chars[i] != chars[i+1]){
chars[write] = chars[mark];
write++;
if(mark < i){
for(char a : (""+(i-mark+1)).toCharArray())
chars[write++] = a;
}
mark = i + 1;
}
}
return write;
}
3.最大子序和
/**
*给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
*
* 示例:
* 输入: [-2,1,-3,4,-1,2,1,-5,4],
* 输出: 6
* 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
*/
最笨的方法便是遍历每一种可能,然后求出最大值。
机智的办法便是首先定义最大值为数组第一位,遍历一遍数组,不断地求和,当总和小于0的时候重新计数,最后比较数组和和最大值的大小,返回最大。
public static int method1(int[] nums) {
int max = nums[0];
int sum = nums[0];
for(int i = 1; i < nums.length; i++){
if(sum < 0){
sum = nums[i];
} else{
sum += nums[i];
}
if(sum > max){
max = sum;
}
}
return max;
}
换一种优雅的写法
public static int method2(int[] nums){
int res = nums[0];
int sum = 0;
for (int num : nums) {
if (sum > 0)
sum += num;
else
sum = num;
res = Math.max(res, sum);
}
return res;
}
4.最后单词的长度
/**
*给定一个仅包含大小写字母和空格 ' ' 的字符串,返回其最后一个单词的长度。
* 如果不存在最后一个单词,请返回 0 。
* 说明:一个单词是指由字母组成,但不包含任何空格的字符串。
*/
看到这道题的第一时间想到的就是正则表达式,这也是最容易实现的方式
public static int method1(String s) {
Pattern pattern=Pattern.compile("\\b[a-zA-Z]+\\b");
Matcher matcher=pattern.matcher(s);
int number=0;
while (matcher.find()){
number=matcher.group().length();
}
return number;
}
如果抛去正则表达式,因为找的是最后一个单词的长度,所以可以采用从后往前找单词的方法,找到第一个字母开始计数,直到找到空格为止
public static int method1(String s) {
Pattern pattern=Pattern.compile("\\b[a-zA-Z]+\\b");
Matcher matcher=pattern.matcher(s);
int number=0;
while (matcher.find()){
number=matcher.group().length();
}
return number;
}
还有一种更为简洁的实现方式,String类提供了trim()方法,只要找到去掉最后空格的长度和倒数第一个空格的位置就ok了
public static int method3(String s) {
return s.trim().length()-s.trim().lastIndexOf(" ")-1;
}