1、判斷一個二進制數中有多少個1
思路1:時間複雜度爲O(二進制數長度)。判斷最右一位是否爲1並賦值"num+=v&0x0x",數右移一位"v>>1",循環直到數爲0。
思路2:時間複雜度爲O(二進制數中1個數)
將二進制數中最右的1置0,v = v&(v-1), num++,循環直到數爲0
int count(int v){
int num = 0;
while(v){
v &= (v-1);
num++;
}
return num;
}
該思路在於(v-1)是將數中最右的1所在位變成0,然後用與運算消除後面產生的1,達到只將最右的1置0的效果。
2、函數Rand5()隨機產生1、2、3、4、5中的一個數,且機率相等,基於該函數如何寫出函數Rand7(),即隨機產生1~7且機率相同
由於Rand5()只是產生離散數1~5,如果只調用一次Rand5()再進行變換,每個數產生的機率仍是1/5,因此該問題的核心在於找出七種不同且出現機率相同的數。
調用N次Rand5()方法,將出現5^N種有序排序,如果直接加減乘除則產生機率不同的數,即使拼湊也難以控制機率相同,因此最好保證5^N種有序排序通過某種運算結果還是5^N種、機率必然相同。而且,5^N個數肯定無法被7整除,因此某些情況出現一定會被踢出,並再次調用Rand7()。
以N=2爲例,即調用2次Rand5(),將兩次結果加起來,爲了保證運算結果還是5^N種、出現機率相同,將第一次運行結果乘以10,即:x
= 10*Rand5() + Rand5()。
x等機率隨機出現(11、12、13、14、15、21、....、25、31、...、35、41、...、45、51、...55)之一,總共25個數。要等機率出現1~7,選擇前21種情況對應,出現後面4種情況出現後重新調用Rand5()。可採用switch語句判斷x = 10*Rand5() + Rand5()實現程序。更好的,我們可以考慮,爲了讓x連續,即選擇
x = 5*(Rand5() - 1)+ Rand5()
x等機率隨機出現(1、2、3、...、25)之一,返回時就不用switch語句判斷,而是返回(x-1)/3+1。
後面剔除的4種情況出現概率爲16%,每次出現後都要再進行上述操作,可以改變N算出最好的概率。
文獻http://www.cricode.com/2456.html講的不錯。
3、給定三個數,如何組合三個數使產生的新數最大,(例58、52、5可組合成58525、58552、52585、....,其中58552最大)
思路:每兩個數比較的時候,將兩個數補成相同長度,補齊策略是補上數左邊相同部分
代碼如下:
import java.util.*;
public class MyCode2{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n1 = sc.nextInt();
int n2 = sc.nextInt();
int n3 = sc.nextInt();
sc.close();
if(isBigger(n1,n2)){
if(isBigger(n1,n3))
if(isBigger(n2,n3))
System.out.println(n1+","+n2+","+n3);
else
System.out.println(n1+","+n3+","+n2);
else
System.out.println(n3+","+n1+","+n2);
}
else{
if(isBigger(n1,n3))
System.out.println(n2+","+n1+","+n3);
else{
if(isBigger(n2,n3))
System.out.println(n2+","+n3+","+n1);
else
System.out.println(n3+","+n2+","+n1);
}
}
}
public static boolean isBigger(int a, int b){
boolean rst = false;
LinkedList<Integer> A = new LinkedList<Integer>();
LinkedList<Integer> B = new LinkedList<Integer>();
LinkedList<Integer> temp = new LinkedList<Integer>();
while(a>0){
A.add(a%10);
a = a/10;
}
while(b>0){
B.add(b%10);
b = b/10;
}
int len = A.size()>B.size()?A.size():B.size();
for(int i=0;i<len;i++){
//System.out.println(i+" "+A.getLast()+" "+B.getLast());
if(A.getLast()>B.getLast()){
rst = true;
break;
}else if(A.getLast()<B.getLast()){
rst = false;
break;
}
else if(A.getLast()==B.getLast()){
temp.addFirst(A.getLast());
A.removeLast();
B.removeLast();
}
if(A.isEmpty()){
A = temp;
}
if(B.isEmpty()){
B = temp;
}
}
return rst;
}
}
示例:
輸入:1 2 3 輸出: 3,2, 1
輸入:58 52 5 輸出:58,5, 52
輸入:5250 52 6 輸出: 6,52,5250
4、商標上的字符串打印後發現字符‘g’和‘9’很難分清,現需採用手段進行補救,首先需找出所有可能產生的字符串,例如“99”,可能被認爲是“99”、“9g“、“g9”、“gg”。
若字符串中字符‘g’和‘9’的總個數是n,則可能產生2^n種情況,並且可以發現其與二進制數有某種相似之處,因此直接將二進制中的‘0’、‘1’與‘g’和‘9’替換即可。代碼如下:
import java.util.*;
public class CodeOne{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
sc.close();
ArrayList<Integer> al = new ArrayList<Integer>();
for(int i=0;i<str.length();i++){
char ch = str.charAt(i);
if(ch=='9'||ch=='g')
al.add(i);
}
int N = (int)Math.pow(2, al.size());
for(int j=0;j<N;j++){
StringBuffer sbur = new StringBuffer(str);
//轉換成二進制字符串並補齊
String binstr = Integer.toBinaryString(j);
while(binstr.length()<al.size()){
binstr = "0"+binstr;
}
System.out.println(binstr);
//二進制與字符替換
for(int k=0;k<al.size();k++){
if(binstr.charAt(k)=='0')
sbur.setCharAt(al.get(k), '9');
else if(binstr.charAt(k)=='1')
sbur.setCharAt(al.get(k), 'g');
}
System.out.println(sbur);
}
}
}
示例:
輸入:99 輸出:99、9g、g9、gg
輸入:0129g 輸出:01299、0129g、012g9、012gg
前3道是2016年攜程機試與面試題,第4道是2016年網易機試題。