给出两个整数 aa 和 bb , 求他们的和。
你不需要从输入流读入数据,只需要根据aplusb
的两个参数a和b,计算他们的和并返回就行。
a和b都是 32位
整数么?
我可以使用位运算符么?
如果 a=1
并且 b=2
,返回3
。
首先肯定要想到用位运算来操作,即用二进制来处理,好,既然想到这里,当然要举个例子来想想,最简单的1+2
1的二进制 ····0001
2的二进制 ····0010
3的二进制 ····0011
那a+b不就等于a|b吗?那么,再来验证下1+3
1的二进制 ····0001
3的二进制 ····0011
4的二进制 ····0100
发现之前的猜想错误了,然后再经过一些其他简单的验算,我们会轻而易举的发现一个规律,如果没有进位,那么a+b = a|b 如果有进位就不成立。
所以接下来要处理进位的问题,我们在用1+3来研究下进位的问题,如果我们忽略有进位的位置后,再加上应该进位的位置,就是我们的值。
1的二进制(a) ····0001
3的二进制(b) ····0011
忽略进位的二进制(c) ····0010(忽略有进位的位),既然忽略了进位,那么接下来肯定要加上进位
应该进位的值(d) ····0010
我们的值应该是c+d(但是c和d还是有进位,那么再重复上述操作),即:
c的二进制 ····0010
d的二进制 ····0010
忽略进位的二进制(e) ····0000
应该进位的值(f) ····0100
结果就是e+f = 4
解决方式:
step1:先计算a和b(忽略进位)(相当于位运算符a^b) a^b:二进制的异或运算
step2:计算应该进位的值(进位)(相当于位运算a&b<<1) a&b<<是二进制的与运算,再左移一位
step3:将上面step1的值和step2的值,相加;如果还有进位,则继续执行step1、step2,直至双方有一个为0时,输出另一方这就是相加的结果。
答案1:
public class Solution {
/**
* @param a: An integer
* @param b: An integer
* @return: The sum of a and b
*/
public int aplusb(int a, int b) {
// write your code here
if (a==0)return b;
if(b==0)return a;
int c=a^b;//二进制取异或,没有进位
int d=(a&b)<<1;//相与再向右移一位,取进位
return aplusb(c,d);
//将c+d的结果还有进位,代入aplus的方法,直至某一个数为零,输出另一个数就//是结果
}
}
答案2:
public static int add( int number_1, int number_2 )
{
int sum = 0;
int carry = 0;
do
{
sum = number_1 ^ number_2;
carry = ( number_1 & number_2 ) << 1;
number_1 = sum;
number_2 = carry;
}
while ( carry != 0 );
return sum;
}
设计一个算法,计算出n阶乘中尾部零的个数
您在真实的面试中是否遇到过这个题? 是
11! = 39916800,因此应该返回 2
O(logN)的时间复杂度
分析
1、2、3、4、5、6、7、8、9、10、11、...101
1-101里,每5个数字,有一个数字的阶层尾部产生零 分别是:5、10、15、20、25、...100 共有101/5=20个
又因为:将5、10、15、20、25、...100
变换成5*(1、2、3、4、5、6、...20)里面又有连续的5个数字
所以又可以变换成5*5*(1、2、3、4)
101所以最终带有的零个数就是
101/5=20
20/5=4
一个24个
设计思路:将n个数据除以5,如果不整除,再放到循环里面求出带有零的个数累加
public class Solution {
/*
* @param n: An integer
* @return: An integer, denote the number of trailing zeros in n!
*/
public long trailingZeros(long n) {
// write your code here, try to do it without arithmetic operators.
long temp=n/5;
long count=0;
while(temp!=0){//如果整除,直接返回结果
count+=temp;//计零的个数
temp/=5;//不满足temp为零,继续除
}
return count;
}
}
给定一个整型数组,找出主元素,它在数组中的出现次数严格大于数组元素个数的二分之一。
给出数组[1,1,1,1,2,2,2],返回 1
要求时间复杂度为O(n),空间复杂度为O(1)
分析:
利用在数组中的出现次数严格大于数组元素个数的二分之一来控制
定义一个初始值和计数器,数组的下一个原始不等于初始值,计数器减一
如果等于初始值计数器加一,如果计数器为一,而输出那时候的值,就是主元素
public class Solution {
/*
* @param nums: a list of integers
* @return: find a majority number
*/
public int majorityNumber(List nums) {
// 利用主元素大于N/2来筛选
int n=1;//存放出现的次数
int temp=nums.get(0);//假设第一个就是主元素
for(int i=1;i
反转一个只有3位数的整数。
123
反转之后是 321
。900
反转之后是 9
。
你可以假设输入一定是一个只有三位数的整数,这个整数大于等于100,小于1000。
public class Solution {
/**
* @param number: A 3-digit number.
* @return: Reversed number.
*/
public int reverseInteger(int number) {
// write your code here
int a,b,c,temp;//
a=number/100;//对一百取余,得百位
b=(number%100)/10;//得十位
c=number%10;//得个位
temp=c*100+b*10+a;//存放反转的数
return temp;
}
}
给出A=[1,2,3,4],B=[2,4,5,6],返回 [1,2,2,3,4,4,5,6]
你能否优化你的算法,如果其中一个数组很大而另一个数组很小?
思路:
1.定义一个长度是A+B长度的数组
2.可能出现的情况:
public class Solution {
/**
* @param A: sorted integer array A
* @param B: sorted integer array B
* @return: A new sorted integer array
*/
public int[] mergeSortedArray(int[] A, int[] B) {
// write your code here
int[] c=new int[A.length+B.length];//创建一个新的数组,长度为两个长度相加
int index1=0;//数组A下标
int index2=0;//数组B下标
int curr=0;//c数组下标
//两两不为空的情况
while(index1
题目描述:给定一个长度为n的整数数组a,元素均不相同,问数组是否存在这样一个片段,只将该片段翻转就可以使整个数组升序排列。其中数组片段[l,r]表示序列a[l], a[l+1], ..., a[r]。原始数组为
a[1], a[2], ..., a[l-2], a[l-1], a[l], a[l+1], ..., a[r-1], a[r], a[r+1], a[r+2], ..., a[n-1], a[n],
将片段[l,r]反序后的数组是
a[1], a[2], ..., a[l-2], a[l-1], a[r], a[r-1], ..., a[l+1], a[l], a[r+1], a[r+2], ..., a[n-1], a[n]。
输入
第一行数据是一个整数:n (1≤n≤105),表示数组长度。 第二行数据是n个整数a[1], a[2], ..., a[n] (1≤a[i]≤109)。
|
样例输入
4 2 1 3 4
|
输出
输出“yes”,如果存在;否则输出“no”,不用输出引号。
|
样例输出
yes |
思路:
1、定义两个数组a、b,赋值一样,长度一样;
2、将数组b进行升序;
3、将数组a的元素依次对应和数组b的左右两边依次比较,记录左边开始数组比较不对应的编号left、记录右边开始两个数值比较不相同的编号right。(2134)(1234)左边开始不相等的编号left=0; 右边比较不相等的编号是right=1;
4、最后比较这段不相等的编号之间,是否满足交叉相等的规律(21)(12)a[left+i]==b[right-i];如果满足这个规律,这输出yes
否则输出no;
package com.demo.day8.list;
import java.util.Arrays;
import java.util.Scanner;
/* 翻转数组。
* 题目描述:给定一个长度为n的整数数组a,元素均不相同,
* 问数组是否存在这样一个片段,只将该片段翻转就可以使整个数组升序排列
* 输入第一行数据是一个整数:n (1≤n≤105),表示数组长度。
* 第二行数据是n个整数a[1], a[2], ..., a[n] (1≤a[i]≤109)。
* 输出输出“yes”,如果存在;否则输出“no”,不用输出引号。
*/
public class ArrayTest {
public static void main(String[] args) {
//从键盘输入数据
Scanner sc=new Scanner(System.in);
while(sc.hasNext()) {
int len=sc.nextInt();//第一个整数是数组的长度
// 1、定义两个数组a、b,赋值一样,长度一样;
int[]a=new int[len];//定义个数组A,长度为len
int[]b=new int[len];//定义个数组B,长度为len
for(int i=0;i
题目描述:
数列的定义如下: 数列的第一项为n,以后各项为前一项的平方根,求数列的前m项的和。
输入
81 4
2 2
输入数据有多组,每组占一行,由两个整数n(n<10000)和m(m<1000)组成,n和m的含义如前所述。
输出
94.73
3.41
对于每组输入数据,输出该数列的和,每个测试实例占一行,要求精度保留2位小数。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
//思路:
/*
* 1定义一个数组长度为m的数组
* 2将第一个数n进行循环开平方保存在数组里面
* 3将数组求和
*/
//从键盘接受数据
Scanner sc=new Scanner(System.in);
while(sc.hasNext()) {//循环输入
double n=sc.nextInt();//数列第一个数
int m=sc.nextInt();//数列的长度
double[] arr=new double[m];//定义一个长度为m的数组保存数据
double num=0;//累加
arr[0]=n;
for(int i=1;i
/*
* 找水仙花数
* 水仙花数”是指一个三位数,它的各位数字的立方和等于其本身,比如:153=1^3+5^3+3^3
* 思路:
* 1、定义一个长度(n-m+1)数组
* 2、取出一个数,并求出百位、十位、个位
* 3、判断是否满足要求存在一个新数组里面,不满足则进行找下一个
*/
package com.test;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main2 {
/*
* 找水仙花数
* 水仙花数”是指一个三位数,它的各位数字的立方和等于其本身,比如:153=1^3+5^3+3^3
* 思路:
* 1、定义一个长度(n-m+1)数组
* 2、取出一个数,并求出百位、十位、个位
* 3、判断是否满足要求存在一个新数组里面,不满足则进行找下一个
*/
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
// String s=sc.nextLine();//读取控制台的一行数据
// String[] array=s.split(" ");//根据空格把数据拆分
int m=sc.nextInt();//区间第一个数
int n=sc.nextInt();//区间最后一个数
//定义一个长度为n-m+1的数组
int[] arr= new int[20];
boolean flag=false;
int j=0;
for(int i=m;i=m&&i<=n) {
int a=i/100;//百位
int b=(i%100)/10;//十位
int c=(i%100)%10;//个位
if((a*a*a+b*b*b+c*c*c)==(a*100+b*10+c))
{
arr[j]=a*100+b*10+c;
j++;
flag=true;
}
}
if(flag==true) {
for(int i=0;i
将一个字符串中的小写字母转换为大写字母。忽略其他不是字母的字符。
样例
给出
"abc"
, 返回"ABC"
.给出
"aBc"
, 返回"ABC"
.给出
"abC12"
, 返回"ABC12"
.思路:
1、定义一个空字符串Newstr
2、取出输入的字符串的每一个元素,判断是否是小写字母
3、如果是小写字母则变成大写并加到Newstr上,如果不是则直接加到Newstr字符串上
public class Solution {
/**
* @param str: A string
* @return: A string
*/
public String lowercaseToUppercase2(String str) {
// write your code here
String newStr ="";//定义一个空字符串
for (int i = 0; i < str.length(); i++){//遍历传进来的字符串
char ch = str.charAt(i);//charAt(i)方法返回第i个元素
if (Character.isLowerCase(ch)){//如果这个元素是小写的
ch = Character.toUpperCase(ch);//则输出大写
}
newStr += ch;//将转换的字符串加一起输出
}
return newStr;
}
}
水仙花数的定义是,这个数等于他每一位上数的幂次之和 见维基百科的定义
比如一个3位的十进制整数
153
就是一个水仙花数。因为 153 = 13 + 53 + 33。而一个4位的十进制数
1634
也是一个水仙花数,因为 1634 = 14 + 64 + 34 + 44。给出
n
,找到所有的n位十进制水仙花数。你可以认为n小于8。
比如 n =
1
, 所有水仙花数为:[0,1,2,3,4,5,6,7,8,9]
。
而对于 n =2
, 则没有2位的水仙花数,返回[]
。
- 1位数范围是[0,9] ; 2位数的范围是[10,99] ;3位数的范围是[100,999]...n位数的范围是[10^(n-1),(10^n)-1]
- 所以做一个循环,1=
- 定义一个pow(m,n)函数,作用返回m的n次方,其中m可以是一个数的个位、十位、百位;
- 定义一个数组装满足水仙花规律的数
package com.test;
import java.util.ArrayList;
public class Solution {
/*
* @param n: The number of digits.
*
* @return: All narcissistic numbers with n digits.
*/
public ArrayList getNarcissisticNumbers(int n) {
// write your code here
/*
* 找水仙花数
* 1.定义一个数组
* 2.定义一个pow(m,n)函数,返回m的n次方的结果
* 3.n位数的范围区间内循环,在里面找满足水仙花数,满足结果则返回
*/
ArrayList result = new ArrayList();
if(n==1)
{
for(int i=0;i<10;i++){
result.add(i);
}
return result;
}
for (int i = pow(10, n - 1); i <= (pow(10, n) - 1); i++) {// n位数的区间
int num = i;
int temp = 0;
for (int j = 0; j < n; j++) {
temp += pow((num % 10), n);// 计算是否满足水仙花数的规律
num = num / 10;// 拿出个位、十位、..
}
if (temp == i) {
result.add(temp);
}
}
return result;
}
public final int pow(int m, int n) {
int val = 1;
for (int i = 1; i <= n; ++i)
val *= m;// 累乘的结果
return val;
}
}
在链表中找值为 value 的节点,如果没有的话,返回空。
给出 1->2->3
和 value = 3, 返回最后一个节点 last node.
给出 1->2->3
和 value = 4, 返回空。
public class Solution {
/*
* @param head: the head of linked list.
* @param val: An integer.
* @return: a linked node or null.
*/
public ListNode findNode(ListNode head, int val) {
// write your code here
while(head!=null){
if(head.val==val){//如果值与当前相等,则返回此时的节点
return head;
}
head=head.next;//如果不符合,继续往下走
}
return head;
}
}
找链表的中点。
链表 1->2->3
的中点是 2
。
链表 1->2
的中点是 1
。
如果链表是一个数据流,你可以不重新遍历链表的情况下得到中点么?
思路:遍历链表得到链表长度,中点的位置是(链表长度-1)/2的下标位置,返回这个节点。
public class Solution {
/**
* @param head: the head of linked list.
* @return: a middle node of the linked list
*/
public ListNode middleNode(ListNode head) {
// 新建一个ListNode对象,为头结点
ListNode ln =head;
int i=0;
while(head!=null){
head=head.next;//遍历链表,直至到尾部,得出链表的长度
i++;
}
for(int j=0;j<(i-1)/2;j++){//找到中间那个数
ln=ln.next;
}
return ln;
}
}
Given a string, convert it to an integer. You may assume the string is a valid integer number that can be presented by a signed 32bit integer (-231 ~ 231-1).
给出 "123"
, 返回 123
.
public class Solution {
/**
* @param str: A string
* @return: An integer
*/
public int stringToInteger(String str) {
// write your code here
//valueOf是Integer类的一个静态方法,
//它是把一个string参数转换为Integer类型
//那么经过Integer.valueOf("345")转换,345就是一个Integer类型了
return Integer.valueOf(str);
}
}