数与位部分刷题记录
数与位的操作
question 7(整数反转)
answer
class Solution {
public int reverse(int x) {
if(x==0){return 0;}
int sum=0;
while(x!=0){
if(sum<(Integer.MIN_VALUE)/10||sum>(Integer.MAX_VALUE)/10){
return 0;
}
sum=sum*10+(x%10);
x=x/10;
}
return sum;
}
}
question9(回文数)
answer
class Solution {
public boolean isPalindrome(int x) {
//若是回文,则正反都一样,把数字倒序存储,比较是否相等
if(x<0){return false;}
int reverse=0;
int temp=x;
while(temp!=0){
reverse=reverse*10+temp%10;
temp=temp/10;
}
if(reverse==x){
return true;
}
return false;
}
}
question479(最大回文数乘积)
answer
遍历暴力解会超时
class Solution {
public int largestPalindrome(int n) {
if(n==1){return 9;}
int max=(int)Math.pow(10,n)-1;
int res=0;
//枚举回文数的左半部分
for(int left=max;res==0;left--){
//构造回文数p
long p=left;
int x=left;
//加上回文数的右半部分
while(x!=0){
p=p*10+x%10;
x/=10;
}
//x*x可能会溢出,用long
for(long i=max;i*i>=p;i--){
//i是p的因子
if(p%i==0){
res=(int)(p%1337);
break;
}
}
}
return res;
}
}
question 564*、
question 231(2的幂)
answer
class Solution {
public boolean isPowerOfTwo(int n) {
while(n>1){
int temp=n%2;
if(temp!=0){
return false;
}
n=n/2;
}
if(n==1){
return true;
}
return false;
}
}
class Solution {
public boolean isPowerOfTwo(int n) {
return n > 0 && (n & (n - 1)) == 0;
}
}
question326(3的幂)
class Solution {
public boolean isPowerOfThree(int n) {
while(n!=0&&n%3==0){
n=n/3;
}
if(n==1){
return true;
}
return false;
}
}
question504(七进制数)
class Solution {
public String convertToBase7(int num) {
StringBuilder sb=new StringBuilder();
if(num==0){
return "0";
}
boolean flag=num<0;
//取绝对值
num=Math.abs(num);
while(num!=0){
sb.append(num%7);
num/=7;
}
if(flag){
sb.append("-");
}
return sb.reverse().toString();
}
}
question263、
answer
class Solution {
public boolean isUgly(int n) {
while(n>1){
if(n%2==0){
n=n/2;
}else if(n%3==0){
n=n/3;
}else if(n%5==0){
n=n/5;
}else{
return false;
}
}
if(n==1){
return true;
}
return false;
}
}
question190 ( 颠倒二进制 )
public class Solution {
// you need treat n as an unsigned value
//n=1101
public int reverseBits(int n) {
int rev = 0;
// 取n最低位放在ret对应位置,n循环右移
for (int i = 0; i < 32 && n != 0; ++i) {
//1101 & 1 = 0001
//1<<(31-0) =10000....
//rev|1000....=10000...
rev |= (n & 1) << (31 - i);
//n=110
n >>= 1;
}
return rev;
}
}
question 191(位1的个数)
answer
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int sum=0;
int i=32;
while(i>0){
if((n&1)==1){
sum++;
}
i--;
n>>=1;
}
return sum;
}
}
question476 (数字的补数)
class Solution {
public int findComplement(int num) {
//1011取反后为0111
//1011 ^ 1111 =0100
int temp=num;
//c用来存储多少个1
int c=0;
while(temp!=0){
temp>>=1;
c=(c<<1)|1;
}
return num^c;
}
}
question461 (汉明距离)
求有几个不同的位
answer
class Solution {
public int hammingDistance(int x, int y) {
// 101 ^ 111 =010 ,相同为0,不同异或为1,
int sum=0;
while(x!=0||y!=0){
int xflag=x&1;
int yflag=y&1;
if(xflag!=yflag){
sum++;
}
x>>=1;
y>>=1;
}
return sum;
}
}
class Solution {
public int hammingDistance(int x, int y) {
int s = x ^ y, ret = 0;
while (s != 0) {
ret += s & 1;
s >>= 1;
}
return ret;
}
}
question477 (汉明距离总和)
answer:
class Solution {
//暴力解法失败
//考虑的是同一比特位上的值是否不同,而不同比特位之间是互不影响的。
//对于数组 nums 中的某个元素 val,若其二进制的第 i 位为 1,我们只需统计 nums 中有多少元素的第 i 位为 0,即计算出了 val 与其他元素在第 i 位上的汉明距离之和。
//由于 10^9<2^30 我们可以直接从二进制的第 0 位枚举到第 29 位。
public int totalHammingDistance(int[] nums) {
int ans=0,n=nums.length;
//枚举二进制的下标
for(int i=0;i<30;i++){
//第i位 1 的个数
int c=0;
for(int val:nums){
//(val>>i)&1 判断第i位是否为1
c+=(val>>i)&1;
}
//第i位 1的个数为 c, 0的个数为(n-c),第i位上的汉明距离为 c*(n-c)
ans+=c*(n-c);
}
return ans;
}
}
question693 (交替位二进制数)、
answer:
class Solution {
public boolean hasAlternatingBits(int n) {
// 如 010101 右移一位得到 001010
// 二者异或之后得到011111 (这一步是关键,只有交替出现01,异或后才能得到结果0111111...11)
// 为了判断 异或后的结果是否满足(0111111...11)类型的结果
// 可以用如下方法,比如
// 011111 加上1 为100000
// 011111 与 100000按位相与 结果为000000 , 也就是0;
int m = n ^ (n >> 1);
return (m & (m + 1)) == 0;
}
}
question393*、
question 172(阶乘后的0)、
answer
n! 尾零的数量即为 n! 中因子 10 的个数,而 10=2×5,因此转换成求 n! 中质因子 2 的个数和质因子 5 的个数的较小值。
由于质因子 5 的个数不会大于质因子 2 的个数,我们可以仅考虑质因子 5 的个数
class Solution {
public int trailingZeroes(int n) {
//统计5的个数
int count = 0;
while(n >= 5) {
count += n / 5;
n /= 5;
}
return count;
}
}
question458 (最大连续1的个数)、
answer
class Solution {
public int findMaxConsecutiveOnes(int[] nums) {
int len=nums.length;
int max=0;
if(len<1){return max;}
int temp=0;
for(int i=0;i<len;i++){
if(nums[i]==1){
temp+=1;
}else{
max=Math.max(max,temp);
temp=0;
}
}
max=Math.max(max,temp);
return max;
}
}
question258(各位相加)、
answer1
class Solution {
public int addDigits(int num) {
while(num>9){
int sum=0;
while(num>0){
sum+=num%10;
num=num/10;
}
num=sum;
}
return num;
}
}
answer2
class Solution {
public int addDigits(int num) {
if (num==0){
return 0;
}else if (num%9==0){
return 9;
}else{
return num%9;
}
}
}
question 319 *
question 405 (数字转换为十六进制数)、
answer
class Solution {
public String toHex(int num) {
//32 位有符号整数的二进制数有 32 位,由于一位十六进制数对应四位二进制数,
//因此 32 位有符号整数的十六进制数有 8 位。
if (num == 0) {
return "0";
}
StringBuffer sb = new StringBuffer();
for (int i = 7; i >= 0; i --) {
//0xff表示的数二进制1111
int val = (num >> (4 * i)) & 0xf;
if (sb.length() > 0 || val > 0) {
char digit = val < 10 ? (char) ('0' + val) : (char) ('a' + val - 10);
sb.append(digit);
}
}
return sb.toString();
}
}
question 171 (Excel表列序号)、
answer
class Solution {
public int titleToNumber(String columnTitle) {
char[] arr=columnTitle.toCharArray();
int res=0;
int len=arr.length;
for(int i=0;i<len;i++){
res=res*26+(arr[i]-'A'+1);
}
return res;
}
}
question168 (Excel表列名称)、
answer
class Solution {
public String convertToTitle(int columnNumber) {
//res=res*26+s[i]-'A'+1
// s[i]-'A'+1 的范围 [1,26],所以%前,我们先减个1
// 现在是反过来而已,res先减1,然后%26,这样去思考就很简单!
StringBuffer sb=new StringBuffer();
while(columnNumber>0){
columnNumber=columnNumber-1;
sb.append((char)((columnNumber%26)+'A'));
columnNumber=columnNumber/26;
}
return sb.reverse().toString();
}
}
question 670 (最大交换)
class Solution {
public int maximumSwap(int num) {
String s = String.valueOf(num);
int len = s.length();
char[] charArray = s.toCharArray();
int max = num;
for (int i = 0; i < len; i++) {
for (int j = i + 1; j < len; j++) {
swap(charArray, i, j);
max = Math.max(max, Integer.parseInt(new String(charArray)));
swap(charArray, i, j);
}
}
return max;
}
private void swap(char[] charArray, int index1, int index2) {
char temp = charArray[index1];
charArray[index1] = charArray[index2];
charArray[index2] = temp;
}
}
question233*、
question 357 (统计各位数字都不同的数字个数)、
answer
斐波那契公式
class Solution {
public int countNumbersWithUniqueDigits(int n) {
//f(0)=1,f(1)=9+f(0),
//f(2)=9*9+f(1)
//f(3)=9*9*8+f(2)
if(n==0){return 1;}
int f=1;
int pre=9;
for(int i=1;i<=n;i++){
f+=pre;
pre=pre*(10-i);
}
return f;
}
}
question 400 (第N位数)*
answer
class Solution {
public int findNthDigit(int n) {
return find(n, 10, 1);
}
int find(long n, long base, int i) {
if (n >= base * i) return find(n + base, base * 10, i + 1);
//第几个整数的第几位
else return String.valueOf(n / i).charAt((int) (n % i)) - '0';
}
}
简单数学题
question 492 (构造矩形)、
answer
class Solution {
public int[] constructRectangle(int area) {
int width=(int)Math.sqrt(area);
while(area%width!=0){
width--;
}
return new int[]{area/width,width};
}
}
question 29 (两数相除)*、
answer 位运算
class Solution {
public int divide(int a, int b) {
if(a == Integer.MIN_VALUE){
if(b == 1){
return Integer.MIN_VALUE;
}else if (b == -1){
return Integer.MAX_VALUE;
}
}
boolean sign = (a < 0) ^ (b < 0);
a = Math.abs(a);
b = Math.abs(b);
int res = 0;
//32次判断
for(int i = 31; i >= 0; i--){
// a >= (b << i) 判断 a是不是大于 b * 2 ^ 31
// res += 2 ^ i
// a -= b * 2 ^ i
// 100 / 3
// i = 5 100 >= 96 (3 * 32)? res += 32, 100 -= 96
// i = 4 4 >= 48 (3 * 16) ? no
// i = 3 4 >= 24 (3 * 8) ? no
// i = 2 4 >= 12 (3 * 4) ? no
// i = 1 4 >= 6 (3 * 2) ? no
// i = 0 4 >= 3 (3 * 1) ? res += 1, 4 -= 3 = 1
if((a >>> i) - b >= 0){
a -= (b << i);
if(res > Integer.MAX_VALUE - (1 << i)){
return sign ? Integer.MAX_VALUE : Integer.MIN_VALUE;
}
res += (1 << i);
}
}
return sign ? -res : res;
}
}
question 507 (完美数)
answer
class Solution {
public boolean checkPerfectNumber(int num) {
int sum=0;
for(int i=1;i<=num/2;i++){
if(num%i==0){
sum+=i;
}
}
return num==sum;
}
}
快速幂
question50 (pow(x,n))、
answer
class Solution {
public double myPow(double x, int n) {
//折半计算,如果偶数,直接把上次递归得到的值算个平方返回即可,
//如果是奇数,则还需要多乘上个x的值
double res=1.0;
for(int i=n;i!=0;i/=2){
if(i%2!=0){
res*=x;
}
x*=x;
}
return n<0 ? 1/res:res;
}
}
question 372(超级次方)
answer
class Solution {
public int superPow(int a, int[] b) {
int ans=1;
for(int i=b.length-1;i>=0;i--){
ans=(int)((long)ans*pow(a,b[i])%1337);
a=pow(a,10);
}
return ans;
}
public int pow(int x,int n){
int res=1;
while(n!=0){
if(n%2!=0){
res=(int)((long)res*x%1337);
}
x=(int)((long)x*x%1337);
n/=2;
}
return res;
}
}