题目描述
小明很喜欢数学,有一天他在做数学作业时,要求计算出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;
}
}
题目描述
输入一个递增排序的数组和一个数字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;
}
}
题目描述
汇编语言中有一种移位指令叫做循环左移(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;
}
}
题目描述
牛客最近来了一个新员工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();
}
}
}
题目描述
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;
}
}
题目描述
每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
如果没有小朋友,请返回-1
思路解析
这题的本质其实是契科夫圆,有兴趣的大家可以去了解一下,这里博主是通过单链表实现的,其实很简单就是每一个轮回计数,当达到m时,就刨除相应位置的元素,如果计数的次数已经超过链表的长度,那么我们就需要通过%这个操作重新将计数归为从1开始,一直这样递归,知道链表只剩下一个元素。
源代码
import java.util.ArrayList;
public class Solution {
public int LastRemaining_Solution(int n, int m)
{
if(n==0)
return -1;
ArrayList<Integer>list=new ArrayList<Integer>();
for(int i=0;i<n;i++)
list.add(i);
int count=0;
while(list.size()>1)
{
for(int i=0;i<m;i++)
{
count++;
if(count>list.size())
{
count%=list.size();
}
}
//注意这里因为是下标,所以我们必须要进行--操作,而且必须是--count不能用count--,否则还是会报越界错误
list.remove(--count);
}
return list.get(0);
}
}
题目描述
求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
思路解析
这里主要是运用了短路原理。其实大家看看应该就能理解,如果是第一次接触
源代码
public class Solution {
public int Sum_Solution(int n) {
int sum=n;
boolean flag=(sum>0)&&((sum+=Sum_Solution(n-1))>0);
return sum;
}
}
题目描述
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
思路解析
这里主要是运用了位求和以及进位的操作
我们先通过10进制来跟大家演示一下
假设我们计算36+19,我们就按照下面的图来皆是:
同样的这样的运算是否也适用于二进制呢,我们同样来试试:
19=10011
35=100011
显然计算下来也是符合我们的规则的,所以我们也可以通过这种方式来计算。
其次我们只要在观察得出位求和与进位操作分别有什么规律?
所以我们就可以通过异或和与操作来帮助我们更快的进行操作。
源代码
public class Solution {
public int Add(int num1,int num2) {
int sum,carry;
do{
sum = num1 ^ num2;
carry = (num1&num2) <<1;
num1 = sum;
num2 = carry;
}while(num2!=0);
return num1;
}
}
题目描述
将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
输入描述:
输入一个字符串,包括数字字母符号,可以为空
输出描述:
如果是合法的数值表达则返回该数字,否则返回0
思路解析
这里我们先判断当前的字符是不是一个数,这里因为他可能会带上符号,所以我们需要将第一个位置的字符单独拿出来讨论。
谈论完成后只需要将是数字字符的部分整合成数字输出即可。
源代码
import java.util.ArrayList;
import java.util.List;
public class Solution {
public boolean panduan(String str)
{
if(str.equals(""))
return false;
char[]ch=str.toCharArray();
if(!((ch[0]>='0'&&ch[0]<='9')||ch[0]=='+'||ch[0]=='-'))
return false;
for(int i=1;i<ch.length;i++)
{
if(!(ch[i]>='0'&&ch[i]<='9'))
return false;
}
return true;
}
public int StrToInt(String str)
{
if(panduan(str))
{
int sum=0;
int count=1;
if(str.charAt(0)=='+')
{
String str1=str.substring(1,str.length());
char[]ch=str1.toCharArray();
List<Integer>list=new ArrayList<Integer>();
for(int i=ch.length-1;i>-1;i--)
list.add(Character.getNumericValue(ch[i]));
for(int i=0;i<list.size();i++)
{
sum+=list.get(i)*count;
count*=10;
}
return sum;
}
else if(str.charAt(0)=='-')
{
String str1=str.substring(1,str.length());
char[]ch=str1.toCharArray();
List<Integer>list=new ArrayList<Integer>();
for(int i=ch.length-1;i>-1;i--)
list.add(Character.getNumericValue(ch[i]));
for(int i=0;i<list.size();i++)
{
sum+=list.get(i)*count;
count*=10;
}
return 0-sum;
}
else
{
char[]ch=str.toCharArray();
List<Integer>list=new ArrayList<Integer>();
for(int i=ch.length-1;i>-1;i--)
list.add(Character.getNumericValue(ch[i]));
for(int i=0;i<list.size();i++)
{
sum+=list.get(i)*count;
count*=10;
}
return sum;
}
}
else
return 0;
}
}
题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
思路解析
这题比较简单循环加入列表中,列表中不存在的就直接添加,如果列表已经存在,那么说明已经是重复的元素,跳出循环输出即可。
源代码
import java.util.ArrayList;
import java.util.List;
public class Solution {
// Parameters:
// numbers: an array of integers
// length: the length of array numbers
// duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
// Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
// 这里要特别注意~返回任意重复的一个,赋值duplication[0]
// Return value: true if the input is valid, and there are some duplications in the array number
// otherwise false
public boolean duplicate(int numbers[],int length,int [] duplication) {
boolean flag=false;
List<Integer>list=new ArrayList<Integer>();
if(numbers==null){}
else
{
list.add(numbers[0]);
for(int i=1;i<length;i++)
{
if(!list.contains(numbers[i]))
list.add(numbers[i]);
else
{
duplication[0]=numbers[i];
flag=true;
break;
}
}
}
return flag;
}
}