LeetCode题解

202、快乐数

题目描述:

编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
示例 1:

输入:n = 19
输出:true
解释:
1+81=82
64+4=68
26+64=100
1+0+0=1
示例 2:

输入:n = 2
输出:false

解题思想:

就是将n中的数分解出来,然后求每个数的平方和是否等于1;但是有问题存在 1、如果这数一个陷入循环怎么办;2、如果这个数不断的增大怎么办,例如2---4---16----37----58----- ;

解决办法:创建一个Set集合,如果n!=1&&!set.contains(n)  set.add(n)

代码:

public boolean isHappy(int n){
  Set<Integer> set=new HashSet<>();
  while(n!=1&&!set.contains(n)){
      set.add(n);
      n=Found(n); 
  }
  return n==1;

}

//计算个数的平方和
public int Found(int n){
  int y=0;
  while(n!=0){
    int x=y%10;
    y+=x*x;
    y=y/10;
   }
  return y; 
}

263、丑数判断

题目描述:

丑数 就是只包含质因数 2、3 和 5 的正整数。
给你一个整数 n ,请你判断 n 是否为 丑数 。如果是,返回 true ;否则,返回 false 。
示例 1:

输入:n = 6
输出:true
解释:6 = 2 × 3

示例 2:
输入:n = 1
输出:true
解释:1 没有质因数,因此它的全部质因数是 {2, 3, 5} 的空集。习惯上将其视作第一个丑数。

示例 3:
输入:n = 14
输出:false
解释:14 不是丑数,因为它包含了另外一个质因数 7 。

解题思想:

该数是丑数表示该数n=2*i+3*j+5*m,即该数可以用2 3 5 的倍数来表示。

因此创建一个数组prim[]用来存放2 3 5,如果该数可以循环的被数组prim整除,则该数就是丑数。

代码:

public boolean isUgly(int n){
int [] prim=new int []{2,3,5};
if(n<0)
  return false;

if(n == 1 || n == 2 || n == 3 || n == 5)
  return true;
if()
for(int i:prim){
   if(n%i==0)
      n=n/i;
 }
 
if(n==1)
  return true;
else
  return false;

}

264、找出第n个丑数

题目描述:

给你一个整数 n ,请你找出并返回第 n 个 丑数 。丑数 就是只包含质因数 2、3 和/或 5 的正整数。

示例 1:
输入:n = 10
输出:12
解释:[1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 个丑数组成的序列。

示例 2:
输入:n = 1
输出:1
解释:1 通常被视为丑数。 

提示:1 <= n <= 1690

解题思想:

1、从1开始不断的循环调用isUgly()函数来判断该数是不是丑数,如果是设标记++,直到标记等于        n;

      该算法思想简单,但是对于每一个数都要调用一次isUgly()函数,效率较低

2、之前有提过丑数就 2i+3j+5m,那么我们就可以利用其定义来获取丑数。

      (1)创建一个优先队列(小顶堆,即父节点最小)来存储丑数

      (2)创建一个Set集合用来判断该数是否已存在

      (3)先将1加入到队列和集合中去

      (4)需要弹出队头元素n次,第n次为我们想要的结果

      (5)对弹出的元素进行2i   3i  5i的操作并调整堆的结构仍为小顶堆

代码:

//第1种解法的代码
public int nthUglyNumber(int n){
    if(n==1)
    return 1;
    int x=1;  //标记此时是第几个丑数
    int y=2;  //从2开始循环

    while(true){
      if(isUgly(y)) //如果该数是丑数,则x++
          x++;
      if(x==n)      //直到x==n
         return x;
      y++;
    }
}
//第2种解题方法

public int nthUglyNumber_2(int n){

  int [] prim =new int []{2,3,5};
  Set<Long> set = new HashSet<Long>();//创建Set集合
  PriorityQueue<Long> queue = new PriorityQueue<Long>();//创建小顶堆

  //将1加入到集合和堆
  set.add(1l);
  queue.offer(1l);

  for(int i=1;i<=n;i++) //第n次弹出的数为我们要的结果
  long x=queue.poll();  //弹出对头元素
  int y=(int)x;
  for(int j:prim){     //对其进行 *2 ,*3 ,*5的操作
     long  h=y*j;
     if(set.add(h))  //set.add(),如果set中不包含添加的元素返回true
       queue.offer(h);
  }
  return y;
}

204、n的质数的数量

题目描述:

给定整数 n ,返回 所有小于非负整数 n 的质数的数量 。

示例 1:
输入:n = 10
输出:4
解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。

示例 2:
输入:n = 0
输出:0

示例 3:
输入:n = 1
输出:0

解题思想:

1、从2开始不断的进行循环,去判断该数是否为质数,如果为质数,则标记加1。这个算法思想简       单,但是超时了。

2、使用埃及筛(详细的可以去看我的上一篇博客)。http://t.csdn.cn/WygNg

代码:

//第1种解题方法(这个方法虽然超时了,但是我想让大家理解一下这个思路)

public int countPrimes(int n){
    if(n<=0)
      return 0;
    int x=0;//用来标记质数的个数
    for(int i=2;i<=n;i++)
    {
        if(judge(i))
          x++;
    } 
    return x;
}

public boolean judge(int n){
    for(int i=2;i<=Math.sqrt(n);i++)
       if(n%i==0)
          return false;
    return true;
}
//第2种解题方法----埃及筛

public int countPrimes_2(int n){

     //创建一个用来标记是否为质数的数组
     int [] prim=new int[n];
     int ans=0;//质数的个数
     //初始化默认全都为质数
     Arrays.fill(prim,1);
     for(int i=2;i<n;i++)
     {
         if(prim[i]==1)
         {    
             ans++;
             if(i*i<n)
             {
                for(int j=i*i;j<n;j+=i)
                   prim[j]=0;
              } 
         }
     }
     return ans;
}

279、完全平方数

题目描述:

给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。

示例 1:
输入:n = 12
输出:3
解释:12 = 4 + 4 + 4

示例 2:
输入:n = 13
输出:2
解释:13 = 4 + 9
 
提示:1 <= n <= 104

解题思路:

使用动态规划的思想来解:

(1)创建一个数组f[i],用来表示最少需要几位数来表示i

(2)使f[i]=i,即最少需要i位数来表示i ;例4=1+1+1+1

(3)进入循环。递推公式为f[i]=Math.min(f[i],f[i-j*j]+1)

代码:

public int Find(int n){

   int [] f=new int [n+1];
   for(int i=1;i<=n;i++)
   {
       f[i]=i;
       for(int j=1;j*j<i;j++)
          f[i]=Math.min(f[i],f[i-j*j]+1);
   }
   return f[n];
}

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值