1.编写一个函数,将一个十六进制字符串转换成整数返回。
既然是编程,那我们就应该有个转换的思路,虽然jdk封装了很多常用的处理问题的方法,但我们应该自己理解理解。
public calss FeelTheBase{
public static int hexToDemcial(String hex){
int sum=0;
int n=0,length=hex.length();
char[] chhex=hex.toUpperCase().toCharArray();
for(int i=0;i'9'&&chhex[length-i-1]<='F') {
switch(chhex[length-i-1]){
case 'F':
n=15;
break;
case 'E':
n=14;
break;
case 'D':
n=13;
break;
case 'C':
n=12;
break;
case 'B':
n=11;
break;
case 'A':
n=10;
break;
}
}else {
n=chhex[length-i-1]-'0';
}
sum+=n*(1<<(4*i));//主要就是这一段!!!
}
return sum;
}
public static void main(String[] args){
String str_hex="abc";
System.out.println("十六进制="+str_hex+"转十进制="+hexToDemcial(str_hex));
}
}
解释:代码很简单,我们主要来解释 “sum+=n(1<<(4*i))” 是什么意思。首先将十六进制转换成二进制(以abc为例):
1010 1011 1100('abc'的二进制)
不难计算abc的十进制:10*28(211+29) + 11*24(27+25+24) + 12*20(23+22)
通过计算,我们发现了一个规律,从最低4位开始的十六进制字符转换成十进制整数依次呈24倍率关系!
2.请设计一个类,该类在同一个进程中只能有一个实例,且该实例允许外部访问。
分析:很明显,这个就是设计模式中的单例模式,随手写下基本构造:
public class singleClass{
private static singleClass single = new singleClass();
public singleClass getSingleClass(){
return single;
}
}
3.编写一个函数,求一个数的二进制表示中位为1的个数,例如9的二进制表示为1001,位为1的个数为2。
分析:不知道出这个题寓意何为,看到求二进制我一下子就想到了Integer.toBinaryString()方法,但感觉这样做的话不对劲,这道题可能是要考察我们的转换思路,那好不多BB下面来敲敲敲代码:
public class BinaryQuestion {
public static void main(String[] args) {
}
/**
* @explain 使用除基倒取余法,依次将余数添加到字符串中
* @param num
* @return
*/
public static int radixDivide(int num) {
int n = 0;
StringBuilder str = new StringBuilder();
while(num!=0) {
str.append(num%2);
num=num/2;
}
char[] ch=str.toString().toCharArray();
for(char c : ch) {
if('1'==c)
n++;
}
return n;
}
/**
* @explain 直接使用Integer.toBinaryString()方法直接计算出二进制
* 快速,方便。
* @param num
* @return
*/
public static int sumOfOne(int num) {
String binary=Integer.toBinaryString(num);
char[] ch=binary.toCharArray();
int n=0;
for(char c : ch) {
if('1'==c)
n++;
}
return n;
}
/**
* @explain 我们知道,在计算机处理中,数都是二进制的,同时根据&(与运算)的方式,我们知道
* 0&0=0,0&1=0,1&1=1我们可以根据这个一位一位的将十进制的二进制求出来
* @param num int型 有32位
* @return
*/
public static String logicalShift(int num) {
StringBuilder bin=new StringBuilder();
//从最高位依次&1得到结果
for(int n=31;n>=0;n--)
bin.append((num>>>n&1));
return bin.toString();
}
}
4.给定一个整数数组(元素值不重复)和目标值,找出数组中两个和等于目标值的数(元素不能重复利用)
例如:数组nums=[1,2,5,7],目标值target=6 --->返回[0,2],因为nums[0]+nums[2]=6
思路:
一、既然是数组,先来最暴力的、野蛮的干法
即依次遍历,一个一个揪出来,那么这样来时间复杂度就为O(n^2)
二、哈希表
野蛮的方法在大数据的情况下,肯定时间会消耗不少,那我们就用空间来换时间,使用哈希表,因为哈希表的特性,查询的时间复杂度理想化下为O(1),我们可以依次遍历数组nums,同时回过头判断哈希表里是否有我们想要的值(target-nums[i]),如果没有则将遍历过的数据nums[i]存放在哈希表中,否则取出目标,打印出结果。
代码如下:
public class Solution {
/**
* @title 暴力算法
* @param nums 目标数组
* @param target 目标值
* @return 在目标数组中的两个数位置的索引
* @summary 时间复杂度O(n^2),空间复杂度O(1)
*/
public static int[] twoSumViolence(int[] nums,int target) {
int[] result = new int[2];
for(int i=0;i
5.这里有 100 张写着数字 1~100 的牌,并按顺序排列着。最开始所有
牌都是背面朝上放置。某人从第 2 张牌开始,隔 1 张牌翻牌。然后第 2,4 , 6, …, 100 张牌就会变成正面朝上。
接下来,另一个人从第 3 张牌开始,隔 2 张牌翻牌(原本背面朝上
的,翻转成正面朝上;原本正面朝上的,翻转成背面朝上)。再接下来,又有一个人从第 4 张牌开始,隔 3 张牌翻牌。
像这样,从第 n 张牌开始,每隔 n- 1 张牌翻牌,直到没有可翻动 的牌为止。
问:最后所有牌不再变动的时候,求所以背面朝上的号码。
用Java实现的代码
public class TurnOverCard {
public static void main(String[] args){
//getNumber01();
getNumber02();
}
/**
* @thinking 我们知道,牌一开始是背面朝上的,第一次翻牌正面朝上,第二次翻牌背面朝上,即对于同一张牌
* 翻了n次,n为奇数的时候是正面朝上,n为偶数的是背面朝上。所以对于此题的问题是找出被"翻了偶数次
* 的牌的号码"。
* 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
* 第一次(2起始) 0 2 0 4 0 6 0 8 0 10 0 12 0 14 0 16
* 第二次(3起始) 0 2 3 4 0 0 0 8 9 0 0 0 0 0 15 16
* 第三次(4起始) 0 2 3 0 0 0 0 0 9 0 0 12 0 0 15 0
* 第四次(5起始) 0 2 3 0 5 0 0 0 9 10 0 12 0 0 0 0
* .
* .
* .
* 通过观察,我们发现号码牌和翻牌的第几次起始位置有某种联系,比如号码牌6 :以2、3、6作为起始翻牌才能够翻到号码牌6
* 如号码牌15 :以3、5、15作为起始位置才能够翻到号码牌15
* 即对于号码牌的每一个约数(1除外,因为我们是从第2作为第一次起始位置)按照从小到大排序依次作为第几次翻牌的起始位置
* 就可以知道会不会翻到这个号码的牌了!!!
*
* 回到我们的问题,我们得出"翻了偶数次的牌的号码"作为结果---->可以再次得出号码牌约数为奇书数个(
* 因为还有1是任何正整数的约数)的为我们想要的结果,如果想到这就觉得结束了那就还是小年轻。
*
* 慢慢已经接近答案了,我们再次深入的思考下,我们随便找出约数个数为奇数的号码
* 例如:16 --->1 2 4 8 16
* 25 --->1 5 15
* 36 --->1 2 3 4 6 9 18 36
* 发现没,都是平方数!!!好嘛,结果等于直接口算!!!
*/
public static void getNumber02(){
int carSum=100;
int result=1;
while(result*result<=carSum){
System.out.print(result*result+" ");
result++;
}
}
/**
* @title 使用HashMap+遍历循环
* 时间复杂度O(n^2)
* 空间复杂度O(n)
*/
public static void getNumber01(){
//使用HasMap储存每张牌的状态和号码
HashMap cards=new HashMap();
//牌组默认是"false",即背面朝上
for(int i=1;i<=100;i++){
cards.put(i,"false");
}
//通过遍历根据要求改变牌的状态
for(int i=2;i<=100;i++) {
for (int j = i; j <= 100; j += i) {
if (cards.get(j).equals("false")) {
cards.replace(j, "true");
} else {
cards.replace(j, "false");
}
}
}
//遍历打印出背面朝上的牌的号码
for(int i=1;i<=100;i++){
if(cards.get(i).equals("false"))
System.out.print(i+" ");
}
}
}
6.假设要把长度为 n 厘米的木棒切分为 1 厘米长的小段,但是 1 根木
棒只能由 1 人切分,当木棒被切分为 3 段后,可以同时由 3 个人分别切
分木棒。
求最多有 m 个人时,最少要切分几次?
例如:n = 8, m = 3 时如下所示,切分 4 次就可以了。
== == == == | == == == == 第一次
== == | == == == == | == == 第二次
== | == == | == == | == == == 第三次
== == == == == == == | == 第四次
== == == == == == == == 最终切完结果
用Java实现的代码
public class DivideClub {
public static void main(String[] args){
System.out.println(getTimes(20,3,1));
System.out.println(getTimes02(20,3));
}
/**
* @thought 采用递归的思想
* @param length 木棒长度
* @param people 人的个数
* @param currents 木棒的个数
* @return 切了多少次
*/
public static int getTimes(int length,int people,int currents){
if(currents>=length){
return 0;
}else if(currents
7.面试题:如何在不使用循环的情况下,求出一个数的二进制中1的个数?