41题解–和为S的连续正数序列
题目描述
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
思路解析
这道题最简单的方法就是枚举,但是这样效率很低,而且很有可能会超时,所以我们必须要做出改进。
既然有了通项公式,那么其实我们也能推出这样一个结论,sum如果在n区间长的连续区间内满足,那么这个n区间长的区间是唯一的,不会存在第二个n长的连续区间满足,从上图我们可以看出。
其次假设刚好区间满足情况,那么区间的元素数是不是只有奇数个和偶数个这两种情况。
这里我们得出结论当区间长度为奇数时,如果sum%区间不为0的话,那么就一定不存在这样一个区间满足
那么到了比较复杂的偶数个的情况了
偶数个的情况时就不能通过奇数的方式来解决了,这时候我们可以通过一开始的通项公式来解决。
既然我们已经确定了当前的区间长度,那么我们就可通过判断该sum是否满足通项公式就能确定是否有这样一个区间满足情况。
下面的代码注释有详细说明
源代码
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; public class Solution { public int figure(int sum) { for(int i=1;i<=sum;i++) { if((i+1)*i==2*sum) return i; if((i+1)*i>2*sum) return i-1; } return 0; } //d表示区间长,n表示是第几个区间,然后计算总和 public int jisuan(int d,int n) { return d*(d+1)/2+(n-1)*d; } //定义排序规则,帮助我们排序 Comparator<ArrayList<Integer>>comparator=new Comparator<ArrayList<Integer>>() { @Override public int compare(ArrayList<Integer> o1, ArrayList<Integer> o2) { return o1.get(0)-o2.get(0); } }; public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer>>list=new ArrayList<ArrayList<Integer>>(); int n=figure(sum); for(int i=2;i<=n;i++) { ArrayList<Integer>list2=new ArrayList<Integer>(); list2.clear(); //区间长为偶数时的情况 if(i%2==0) { //计算sum与区间长为i的第一区间的差值 int cha=sum-jisuan(i, 1); //如果差值刚好可以将区间长度整除就说明存在这样的连续区间,这里的区间长同时也是上述通项公式中的公差 if(cha%i==0) { for(int j=1;j<i+1;j++) list2.add(j+(cha/i)); list.add(list2); } } //区间长为奇数时的情况 else { if(sum%i==0) { int count=sum/i-i/2; for(int j=0;j<i;j++) list2.add(count+j); list.add(list2); } } } Collections.sort(list, comparator); return list; } }
42题解–和为S的两个数字
题目描述
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
输出描述:
对应每个测试案例,输出两个数,小的先输出。
思路解析
这题比较简单,只要循环查找就行了,中途记得比较保留最小乘积的两个元素即可。
源代码
import java.util.ArrayList; public class Solution { public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) { ArrayList<Integer>list1=new ArrayList<Integer>(); ArrayList<Integer>list2=new ArrayList<Integer>(); int flag=Integer.MAX_VALUE; int num=1; for(int i=0;i<array.length;i++) list2.add(array[i]); for(int i=0;i<array.length;i++) { if(list2.contains(sum-array[i])) { num=(sum-array[i])*array[i]; if(num<flag) { list1.clear(); flag=num; list1.add(Math.min(sum-array[i], array[i])); list1.add(Math.max(sum-array[i], array[i])); } } } return list1; } }
43题解–左旋转字符串
题目描述
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!
思路解析
这题也比较简单只需要通过String自带的截取函数即可实现,只要注意截取函数是左闭右开的即可。
源代码
public class Solution { public String LeftRotateString(String str,int n) { String str1=""; if(str==null) return str1; if(n>str.length()) return str1; String str2=str.substring(0, n); String str3=str.substring(n, str.length()); str1+=str3; str1+=str2; return str1; } }
44题解–翻转单词顺序列
题目描述
牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
思路解析
这里只要将整个字符串以空格为标志分割成字符数组即可,之后依次添加字符和空格即可,记得将最后一个空格取出即可。
源代码
public class Solution { public String ReverseSentence(String str) { if(str.length()==0||str==null) return str; else { String []str1=str.split(" "); StringBuffer str2=new StringBuffer(); if(str1.length==0) return str; for(int i=str1.length-1;i>-1;i--) { str2.append(str1[i]); str2.append(" "); } if(str2.length()>0) str2.deleteCharAt(str2.length()-1); return str2.toString(); } } }
45题解–扑克牌顺子
题目描述
LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)…他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子…LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。
思路解析
这题主要考察数学知识即可。
首先我们知道顺子代表的就是5个连续的数,所以这5个数各不相同的。但是又因为有大小王这种万能牌的存在,所以我们在排除0的情况下如果有相同的元素那么就一定不能构成顺子,这里大家可以先判断,不要像博主一样写在一个判断语句中。
找一下规律
接着我们只需要对大小王的个数进行分情况讨论即可。
源代码
import java.util.Arrays; public class Solution { public boolean isContinuous(int [] numbers) { Arrays.sort(numbers); if(numbers.length==0) return false; //有四张大小王这种万能牌 if(numbers[3]==0) return true; if(numbers[2]==0&&numbers[4]-numbers[3]<=4&&numbers[4]!=numbers[3]) return true; if(numbers[1]==0&&numbers[4]-numbers[2]<=4&&numbers[4]>numbers[3]&&numbers[3]>numbers[2]) return true; if(numbers[0]==0&&numbers[4]-numbers[1]<=4&&numbers[4]>numbers[3]&&numbers[3]>numbers[2]&&numbers[2]>numbers[1]) return true; if(numbers[4]-numbers[0]==4) return true; return false; } }