31、给定一个数组A[0,1,…,n-1],请构建一个数组B[0,1,…,n-1],其中B中的元素B[i]=A[0]A[1]…A[i-1]*A[i+1]…*A[n-1]。不能使用除法。
package cn.ctgu.offer;
/*
* 题目:
* 给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1]
* 其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。
*
* 思路:
* 1、B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]
* 2、从左到右算 B[i]=A[0]*A[1]*...*A[i-1]
* 3、从右到左算B[i]*=A[i+1]*...*A[n-1]
*
* 解释下代码,设有数组大小为5。
* 对于第一个for循环
* 第一步:b[0] = 1;
* 第二步:b[1] = b[0] * a[0] = a[0]
* 第三步:b[2] = b[1] * a[1] = a[0] * a[1];
* 第四步:b[3] = b[2] * a[2] = a[0] * a[1] * a[2];
* 第五步:b[4] = b[3] * a[3] = a[0] * a[1] * a[2] * a[3];
*
* 然后对于第二个for循环
* 第一步
* b[4]=b[4] *ret= b[4];
* ret=ret*a[4]=a[4]
*
* 第二步
* b[3]=b[3]*ret=b[3] * a[4];
* ret=ret*a[3]=a[4]*a[3]
*
* 第三步
* b[2]=b[2]*ret=a[0]*a[1]*a[4]*a[3];
* ret=ret*[a2]=a[4]*a[3]*[a2]
*
* 第四步
* b[1]=b[1]*ret=a[0]*a[4]*a[3]*a[2];
* ret=ret*a[1]=a[4]*a[3]*a[2]*a[1]
*
* 第五步
* b[0]=b[0]*ret=1*a[4]*a[3]*a[2]*a[1]=a[4]*a[3]*a[2]*a[1]
* ret=a[4]*a[3]*a[2]*a[1]*a[0]
* * */
public class Mulitp {
public int[] multiply(int[] A) {
int n=A.length;
int[]b=new int[n];
int ret=1;
for(int i=0;i1;
for(int i=n-1;i>=0;i--) {
b[i]=b[i]*ret;
ret=ret*A[i];
}
return b;
}
}
32、输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
package cn.ctgu.offer;
import java.util.LinkedList;
/*
* 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
*
* 思路:
* 1、先判断其是否为负数,如果为负数则将其转化为补码
* 2、如果为正数则将其转换为二进制表示的数,并将其存在int类型数组中
* 3、用0xFF与该数做异或运算,相同为0,不同为1,并将结果存在数组中,计算出为0的个数也就是1的个数
*
*
* */
public class OneInNumber {
public int NumberOf1(int n) {
int count=0;
if(n>0) {
String nums=getBinary(n);
for(int i=0;iif(nums.charAt(i)=='1') {
count+=1;
}
}
}else {
int t=0;
StringBuilder sb=new StringBuilder();
for (int i = 0; i < 32; i++)
{
// 0x80000000 是一个首位为1,其余位数为0的整数
t = (n & 0x80000000 >>> i) >>> (31 - i); //负数的补码
sb.append(t);
}
String nums=sb.toString();
for(int i=0;iif(nums.charAt(i)=='1') {
count+=1;
}
}
}
return count;
}
//该函数主要用于将十进制数转为二进制数
public static String getBinary(int num) {
int currentNum=num;
LinkedListlist=new LinkedList();
while(currentNum!=0) {
if(currentNum%2==0) {
list.addFirst("0");
}else {
list.addFirst("1");
}
currentNum/=2;
}
StringBuilder sb=new StringBuilder();
for(int i=0;iget(i));
}
return sb.toString();
}
//这个最简单
public int NumberOf2(int n) {
int t=0;
char[]ch=Integer.toBinaryString(n).toCharArray();
for(int i=0;iif(ch[i]=='1'){
t++;
}
}
return t;
}
/*
* 如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。
* 其余所有位将不会受到影响。
举个例子:一个二进制数1100,从右边数起第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011.
我们发现减1的结果是把最右边的一个1开始的所有位都取反了。
这个时候如果我们再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。
如1100&1011=1000.也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。
* */
public int NumberOf3(int n) {
int count = 0;
while(n!= 0){
count++;
n = n & (n - 1);
}
return count;
}
public static void main(String[]args) {
OneInNumber num=new OneInNumber();
System.out.println(num.NumberOf1(-2147483648));
/*for (int i = 0; i < 32; i++)
{
// 0x80000000 是一个首位为1,其余位数为0的整数
int t = (-2147483648 & 0x80000000 >>> i) >>> (31 - i); //负数的补码
System.out.println(t);
}*/
}
}
33、输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
package cn.ctgu.offer;
import java.util.ArrayList;
/*
*
* 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,
* 例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
* 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
*
* 思路:
* 1、每一圈从左到右,从上到下,然后从右到左,从下到上
* 2、当从右到左的时候需要判断舍掉对右下角的元素(因为从上到下已经打印了)
* 3、当从下到上的时候需要舍掉左上角的元素(因为从左到右已经打印了)
* 4、终止条件为top==bottom right==left
*
* */
import java.util.Iterator;
public class PrintMatrix {
public ArrayList printMatrix(int [][] matrix) {
int rows=matrix.length;
int columns=matrix[0].length;
int top=0;
int bottom=rows-1;
int left=0;
int right=columns-1;
ArrayListarray=new ArrayList();
if(rows==0||columns==0) {
return null;
}
while(top<=bottom&&left<=right) {
for(int i=left;i<=right;i++) {
array.add(matrix[top][i]);//从左到右打印
}
for(int j=top+1;j<=bottom;j++) {
array.add(matrix[j][right]);//从上到下打印
}
if(top!=bottom) { //考虑只有一行的情况
for(int i=right-1;i>=left;i--) {
array.add(matrix[bottom][i]);//从右到左打印
}
}
if(right!=left) { //考虑只有一列的情况
for(int j=bottom-1;j>=top+1;j--) {
array.add(matrix[j][left]);//从下到上打印
}
}
left++;
right--;
top++;
bottom--;
}
return array;
}
public static void main(String[]args) {
int[][]matrix= {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16},{17,18,19,20}};
PrintMatrix print=new PrintMatrix();
ArrayList array=new ArrayList();
array=print.printMatrix(matrix);
Iterator it=array.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
34、输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
package cn.ctgu.offer;
import java.util.ArrayList;
/*
* 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。
* 假设压入栈的所有数字均不相等。
* 例如序列1,2,3,4,5是某栈的压入顺序
* 序列4,5,3,2,1是该压栈序列对应的一个弹出序列
* 但4,3,5,1,2就不可能是该压栈序列的弹出序列。
* (注意:这两个序列的长度是相等的)
*
* 思路:
* 1、当两个长度不相等时则返回false
* 2、当长度为1,值不相等时返回false
* 3、小于第一个弹出的元素的所有索引必须是顺序的,没必要紧挨,但一定得保持前后顺序
*
*
* */
public class PushAndPopStack {
public boolean IsPopOrder(int [] pushA,int [] popA) {
boolean flag=true;
if(pushA.length!=popA.length) {
flag=false;
return flag;
}
if(pushA.length==1) {
if(pushA[0]==popA[0]) {
return flag;
}else {
flag=false;
return flag;
}
}
ArrayListarray=new ArrayList();
int index=Find(pushA,popA[0]);
int j=0;
if(index==-1) {
flag=false;
return flag;
}else {
for(int i=0;i//找出所有小于第一个出栈元素的索引,当这些索引不是递增关系则不可能是该压栈的弹出序列
}
while(j!=(array.size()-1)) {
if(array.get(j)get(j+1)) {
flag=false;
return flag;
}else {
j++;
}
}
}
return flag;
}
//查找弹出的第一个元素在栈中的位置
public int Find(int [] pushA,int target) {
int i=0;
while(target!=pushA[i]&&ireturn i;
}
public static void main(String[]args) {
int[]pushA={1,2,3,4,5};
int[]popA={4,5,3,2,1};
int[]popB={4,3,5,1,2};
int[]pushOne= {1};
int[]popOne= {2};
PushAndPopStack stack=new PushAndPopStack();
if(stack.IsPopOrder(pushA, popA)) {
System.out.println("popA是弹出序列");
}else {
System.out.println("popA不是弹出序列");
}
if(stack.IsPopOrder(pushA, popB)) {
System.out.println("popB是弹出序列");
}else {
System.out.println("popB不是弹出序列");
}
if(stack.IsPopOrder(pushOne, popOne)) {
System.out.println("popB是弹出序列");
}else {
System.out.println("popB不是弹出序列");
}
}
}
链接:https://www.nowcoder.com/questionTerminal/d77d11405cc7470d82554cb392585106
来源:牛客网
/*思路:先循环将pushA中的元素入栈,遍历的过程中检索popA可以pop的元素
**如果循环结束后栈还不空,则说明该序列不是pop序列。
**文字有点难说明白,看代码。
*/
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public boolean IsPopOrder(ArrayList<Integer> pushA,ArrayList<Integer> popA) {
Stack stack = new Stack();
if( pushA.size() == 0 && popA.size() == 0 ) return true;
for( int i=0,j=0; i < pushA.size(); i++ ){
stack.push( pushA.get(i) );
while( ( !stack.empty() )&& ( stack.peek() == popA.get(j) ) ){
stack.pop();
j ++;
}
}
return stack.empty() == true;
}
}
35、在一个长度为n的数组里的所有数字都在0到n-1的范围内。数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
package cn.ctgu.offer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
/*
* 题目:
* 在一个长度为n的数组里的所有数字都在0到n-1的范围内。
* 数组中某些数字是重复的,但不知道有几个数字是重复的。
* 也不知道每个数字重复几次。请找出数组中任意一个重复的数字。
* 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},
* 那么对应的输出是第一个重复的数字2。
*
* 思路:
* 1、采用hashMap
* 2、统计每个数字出现的次数
* 3、输出第一个串重复的数字
*
* */
public class RepeatNumber {
public boolean duplicate(int numbers[],int length,int [] duplication) {
Mapmap=new HashMap();
for(int i=0;i<length;i++) {
int key=numbers[i];
int count=0;
for(int j=0;j<length;j++) {
if(key==numbers[j]) {
count=count+1;
}
map.put(key, count);
}
}
Iterator>iter=map.entrySet().iterator();
ArrayListdata=new ArrayList();
while(iter.hasNext()) {
Map.Entryentry=iter.next();
if(entry.getValue()>=2) {
data.add(entry.getKey());
}
}
Random rand=new Random();
if(data.size()>0) {
int index=rand.nextInt(data.size());
duplication[0]=data.get(index);
return true;
}else {
return false;
}
}
}
/*import java.util.*;
public class Solution {
public boolean duplicate(int numbers[],int length,int [] duplication) {
//方法1:
if(numbers == null || numbers.length == 0) return false;
Arrays.sort(numbers);
int flag = 0;//做标记
for(int i=0;i<length-1;i++) {
if(numbers[i] == numbers[i+1]) {
duplication[0] = numbers[i];
flag = 1;
break;
}
}
return flag == 1? true:false;
//方法2:
HashSet hs = new HashSet<>();
for(int i=0;i<length;i++) {
if(!hs.add(numbers[i])) {
duplication[0]=numbers[i];
return true;
}
}
return false;
}
}*/
36、请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
package cn.ctgu.offer;
/*
* 请实现一个函数,将一个字符串中的空格替换成“%20”。
* 例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
*
* */
public class ReplaceBlank {
/*
* 依次获取StringBuffer中的每一个字符,当它为空格的时候则将其替换成字符串"%20"
* 注意:当我们替换成字符串之后,StringBuffer中的字符会自动往后移,长度也会自动增加
*
* */
public String replaceSpace(StringBuffer str) {
for(int i=0;i<=str.length()-1;i++) {
if(str.charAt(i)==' ') {
str.replace(i, i+1, "%20");//它会把"20%"当做一个子串插入进去,所以是i+1而不是i+3
i=i+2;
}
}
return str.toString();
}
public static void main(String[] args) {
ReplaceBlank replaceBlank=new ReplaceBlank();
StringBuffer st=new StringBuffer("hello world ");
String s=replaceBlank.replaceSpace(st);
System.out.println(s);
}
}
37、牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。
package cn.ctgu.offer;
/*
* 题目:
* 牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。
* 同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。
* 例如,“student. a am I”。
* 后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。
*
*
* 思路:
* 1、按空格将字符串切割成字符串数组
* 2、倒序
*
*
* */
public class ReverseSenten {
public String ReverseSentence(String str) {
if(str.length()==0) {
return "";
}
if(str.trim().equals("")) {
return str;
}
String[]arr=str.split("\\s+");
String s="";
for(int i=arr.length-1;i>=0;i--) {
s=s+" "+arr[i];
}
return s.trim();
}
public static void main(String[]args) {
ReverseSenten solution=new ReverseSenten();
String str="student. a am I";
String s=solution.ReverseSentence(str);
System.out.println(s);
}
}
38、把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
package cn.ctgu.offer;
/*
* 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
* 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
* 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
* NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
*
* */
public class RotateArray {
public int[] minNumberInRotateArray(int [] array) {
int j=0;
int []tempArray=new int[array.length];
if(array.length==0) {
array[0]=0;
return array;
}
if(array.length==1) {
return array;
}else {
for(int i=0;i<=array.length-3;i++) {
if(array[i]>array[i+1]&&array[i+1]<array[i+2]) {
j=i+1;//j元素为数组中最小的一个数
}
}
int len=array.length-j;
int []pre=new int[j];
int []back=new int[len];
for(int i=0;i<=j-1;i++) {
pre[i]=array[i];
}
for(int k=j;k<=array.length-1;k++) {
back[k-j]=array[k];
}
for(int temp=0;temp<=pre.length-1;temp++) {
tempArray[len+temp]=pre[temp];
}
for(int b=0;b<=back.length-1;b++) {
tempArray[b]=back[b];
}
}
return tempArray;
}
public static void main(String[]args) {
RotateArray rotateArray=new RotateArray();
int[] array={1,1,1,1,1};
int[]temp=new int[array.length];
temp=rotateArray.minNumberInRotateArray(array);
System.out.println(array[0]);
System.out.println("--------------------------");
for(int i=0;i<=array.length-1;i++) {
System.out.println(temp[i]);
}
}
}
39、输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
package cn.ctgu.offer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/*
* 输入一个字符串,按字典序打印出该字符串中字符的所有排列。
* 例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
*
*
* 思路:
* 1、将字符串转成字符串数组
* 2、字符串数组进行排列组合
* 3、将排列组合后的字符串数组转成字符串
* 4、比较字符串大小
* */
public class SortString {
public ArrayList Permutation(String str) {
List resultList = new ArrayList<>();
if(str.length() == 0)
return (ArrayList)resultList;
//递归的初始值为(str数组,空的list,初始下标0)
fun(str.toCharArray(),resultList,0);
Collections.sort(resultList);
return (ArrayList)resultList;
}
private void fun(char[] ch,List list,int i){
//这是递归的终止条件,就是i下标已经移到char数组的末尾的时候,考虑添加这一组字符串进入结果集中
if(i == ch.length-1){
//判断一下是否重复
if(!list.contains(new String(ch))){
list.add(new String(ch));
return;
}
}else{
//这一段就是回溯法,这里以"abc"为例
//递归的思想与栈的入栈和出栈是一样的,某一个状态遇到return结束了之后,会回到被调用的地方继续执行
//1.第一次进到这里是ch=['a','b','c'],list=[],i=0,我称为 状态A ,即初始状态
//那么j=0,swap(ch,0,0),就是['a','b','c'],进入递归,自己调自己,只是i为1,交换(0,0)位置之后的状态我称为 状态B
//i不等于2,来到这里,j=1,执行第一个swap(ch,1,1),这个状态我称为 状态C1 ,再进入fun函数,此时标记为T1,i为2,那么这时就进入上一个if,将"abc"放进list中
/////////////-------》此时结果集为["abc"]
//2.执行完list.add之后,遇到return,回退到T1处,接下来执行第二个swap(ch,1,1),状态C1又恢复为状态B
//恢复完之后,继续执行for循环,此时j=2,那么swap(ch,1,2),得到"acb",这个状态我称为C2,然后执行fun,此时标记为T2,发现i+1=2,所以也被添加进结果集,此时return回退到T2处往下执行
/////////////-------》此时结果集为["abc","acb"]
//然后执行第二个swap(ch,1,2),状态C2回归状态B,然后状态B的for循环退出回到状态A
// a|b|c(状态A)
// |
// |swap(0,0)
// |
// a|b|c(状态B)
// / \
// swap(1,1)/ \swap(1,2) (状态C1和状态C2)
// / \
// a|b|c a|c|b
//3.回到状态A之后,继续for循环,j=1,即swap(ch,0,1),即"bac",这个状态可以再次叫做状态A,下面的步骤同上
/////////////-------》此时结果集为["abc","acb","bac","bca"]
// a|b|c(状态A)
// |
// |swap(0,1)
// |
// b|a|c(状态B)
// / \
// swap(1,1)/ \swap(1,2) (状态C1和状态C2)
// / \
// b|a|c b|c|a
//4.再继续for循环,j=2,即swap(ch,0,2),即"cab",这个状态可以再次叫做状态A,下面的步骤同上
/////////////-------》此时结果集为["abc","acb","bac","bca","cab","cba"]
// a|b|c(状态A)
// |
// |swap(0,2)
// |
// c|b|a(状态B)
// / \
// swap(1,1)/ \swap(1,2) (状态C1和状态C2)
// / \
// c|b|a c|a|b
//5.最后退出for循环,结束。
for(int j=i;j1);
swap(ch,i,j);
}
}
}
//交换数组的两个下标的元素
private void swap(char[] str, int i, int j) {
if (i != j) {
char t = str[i];
str[i] = str[j];
str[j] = t;
}
}
}
40、 将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。
package cn.ctgu.offer;
/*
* 题目:
* 将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0)
* 要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。
*
* 输入描述:
* 输入一个字符串,包括数字字母符号,可以为空
* +2147483647
1a33
* 输出描述:
* 如果是合法的数值表达则返回该数字,否则返回0
* 2147483647
* 0
*
* 思路:
* 1、处理+、-,如果为+则最终的结果乘以1,否则乘以-1
* 2、判断是否合法
*
*
* */
public class String2Int {
public int StrToInt(String str) {
char[]strArray=str.toCharArray();
if(str.isEmpty()) {
return 0;
}
int symbol=1;
if(strArray[0]=='-') {//处理负号
symbol=-1;
strArray[0]='0';//之所以要将strArray[0]置位'0'是方便后面进行strArray[i]-'0'运算
}else if(strArray[0]=='+') {//处理正号
symbol=1;
strArray[0]='0';
}
int sum=0;
for(int i=0;iif(strArray[i]<'0'||strArray[i]>'9') {
sum=0;
break;
}
sum=sum*10+strArray[i]-'0';//数字与数字的Ascii码是连着的,数字与它们相加减其实是与其Ascii码相加减的,但是Ascii码的差值和实际数字的差值是个固定,所以可行
}
return symbol*sum;
}
public static void main(String[]args) {
System.out.println(1+'2');//51
System.out.println(51-'1');//2;与字符相加减实际上是与字符的Ascii码相加减,字符先转成int型然后执行加减运算的
System.out.println("2"+1);//结果21
System.out.println(1+"2");//12
}
}
41、写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
package cn.ctgu.offer;
/*
* 题目:
* 写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
*
* 思路:
* 1、用位运算
* 2、首先看十进制是如何做的: 5+7=12,三步走
* 3、相加各位的值,不算进位(用异或运算)
* 相加各位的值,不算进位,得到010,二进制每位相加就相当于各位做异或操作,101^111。得到2,二进制每位相加就相当于各位做异或操作,101^111=010
*
* 4、计算进位值(用与运算,然后左移一位),得到10,如果这一步的进位值为0,那么第一步得到的值就是最终结果
* 计算进位值,得到1010,相当于各位做与操作得到101,再向左移一位得到1010,(101&111)<<1。
*
* 5、否则重复上述两步,只是相加的值变成上述两步得到的结果2和10,得到12
*
*
* */
public class TwoNumberAdd {
public int Add(int num1,int num2) {
while(num2!=0) {
int temp=num1^num2;
num2=(num1&num2)<<1;
num1=temp;
}
return num1;
}
}
42、把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
package cn.ctgu.offer;
/*
* 题目:
* 把只包含质因子2、3和5的数称作丑数(Ugly Number)。
* 例如6、8都是丑数,但14不是,因为它包含质因子7。
* 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
*
* 思路:
* 1、丑数的定义是1或者只有2、3、5可推出丑数=丑数*丑数
* 假定丑数有序序列为:a1,a2,a3.......an 所以可以将以上序列(a1除外)可以分成3类
* 2、必定满足: 包含2的有序丑数序列:2*a1, 2*a2, 2*a3 .....
* 包含3的有序丑数序列:3*a1, 3*a2, 3*a3 .....
* 包含5的有序丑数序列:5*a1, 5*a2, 5*a3 ..... 以上3个序列的个数总数和为n个
* 3、而且已知a1 = 1了,将以上三个序列合并成一个有序序列即可
*
*
* */
public class UglyNumber {
public int GetUglyNumber_Solution(int index) {
int []arr = new int [index];
if(index==0)
return 0;
arr[0]=1;
int t2=0,t3=0,t5=0; //第一个丑数为1,放入数组第一个元素
for(int i=1;i<index;i++)
{
//通过1依次乘2,3,5找到后面的丑数,再通过找到的丑数依次乘2,3,5找到后面的,排序即可
arr[i]=Math.min(arr[t2]*2,Math.min(arr[t3]*3,arr[t5]*5));
if(arr[t2]*2==arr[i])
t2++;
if(arr[t3]*3==arr[i])
t3++;
if(arr[t5]*5==arr[i])
t5++;
}
return arr[index-1];
}
}