《剑指offer》算法题第九天

今日题目:

  1. 整数中1出现的次数
  2. 把数组排成最小的数
  3. 丑数
  4. 第一个只出现一次的字符位置

今天的题目相对比较难,特别是第1题和第3题很考验数学功底,下面我们一题一题来看看。

1.整数中1出现的次数

题目描述:
输入一个整数n,求1~n这n个整数的十进制表示中1出现的次数。例如,输入12,1~12这些整数中包含1的数字有1,10,11,和12,1一共出现了5次。

思路:这道题分别有递归和迭代两种解法,第一次看见这个题目比较难想到,可参考:递归:http://blog.csdn.net/gatieme/article/details/51292339

代码如下:

 1 //递归
 2 public class Solution {
 3     public int NumberOf1Between1AndN_Solution(int n) {
 4         if(n == 0) return 0;
 5         else if(n > 0 && n < 10) return 1;
 6         else{
 7             int high = n;
 8             int weight = 1;
 9             while(high >= 10){
10                 high /= 10;
11                 weight *= 10;
12             }
13
14             if(high == 1){
15                 return NumberOf1Between1AndN_Solution(weight-1)+
16                     NumberOf1Between1AndN_Solution(n-weight)+
17                     (n - weight + 1);
18             }else{
19                 return high*NumberOf1Between1AndN_Solution(weight-1)+
20                     NumberOf1Between1AndN_Solution(n - high*weight)+
21                     weight;
22             }
23
24         }
25     }
26 }
27
28
29 //迭代
30 public class Solution {
31     int NumberOf1Between1AndN_Solution(int n){
32         int ones = 0;
33         for (int m = 1; m <= n; m *= 10) {
34             int a = n/m, b = n%m;
35             if(a%10 == 0)
36                 ones += a / 10 * m;
37             else if(a%10 == 1)
38                 ones += (a/10*m) + (b+1);
39             else
40                 ones += (a/10+1)* m;
41         }
42         return ones;
43     }
44 }

2.把数组排成最小的数

题目描述:
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

思路:重新定义一种比较方法,然后对数组进行排序,最后再输出,博主这边是维护了一个最小堆。

代码如下:

 1 public class Solution {
 2     public String PrintMinNumber(int [] numbers) {
 3         PriorityQueue<String> minHeap = new PriorityQueue(new Comparator<String>(){
 4             public int compare(String str1,String str2){
 5                 String str_12 = str1+str2;
 6                 String str_21 = str2+str1;
 7                 return str_12.compareTo(str_21);
 8             }
 9         });
10         for(int n:numbers){
11             minHeap.add(""+n);
12         }
13         StringBuffer sb = new StringBuffer();
14         while(!minHeap.isEmpty()){
15             sb.append(minHeap.poll());
16         }
17         return sb.toString();
18     }
19 }

3. 丑数

题目描述:
把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

思路:由丑数的定义,每个丑数都是可以由比他小的丑数乘以2,3,或者5得到的,所以这边维护了一个数组和三个分别指向下一步将乘以2,3,或者5的数的指针,这样方便来求解下一个丑数,减小时间复杂度。

代码如下:

 1 public class Solution {
 2     public int GetUglyNumber_Solution(int index) {
 3         if(index <= 0) return 0;
 4         int[] ugly_nums = new int[index];
 5         ugly_nums[0] = 1;
 6         int next = 1;
 7
 8         int p2 = 0,p3 = 0,p5 = 0;
 9         while(next < index){
10             //找到下一个丑数
11             int min = Min(ugly_nums[p2]*2,
12                          ugly_nums[p3]*3,ugly_nums[p5]*5);
13             ugly_nums[next] = min;
14             //移动指针,将它们指向下一个该乘的数
15             while(ugly_nums[p2]*2 <= ugly_nums[next])
16                 p2++;
17             while(ugly_nums[p3]*3 <= ugly_nums[next])
18                 p3++;
19             while(ugly_nums[p5]*5 <= ugly_nums[next])
20                 p5++;
21
22             next++;
23         }
24         return ugly_nums[next-1];
25     }
26
27     public int Min(int num1,int num2,int num3){
28         int min = (num1 > num2)?num2:num1;
29         return min<num3?min:num3;
30     }
31 }

4.第一个只出现一次的字符位置

题目描述:
在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置。

思路:比较简单,维护一个hashmap,将字符和出现的次数放入表中。

代码如下:

 1 import java.util.*;
 2 public class Solution {
 3     public int FirstNotRepeatingChar(String str) {
 4         if(str.length() <= 0) return -1;
 5         HashMap<Character,Integer> map = new HashMap();
 6         for(int i = 0; i < str.length(); i++){
 7             char c = str.charAt(i);
 8             if(!map.containsKey(c)){
 9                 map.put(c,1);
10             }else{
11                 int val = map.get(c);
12                 map.put(c,val+1);
13             }
14         }
15         for(int i = 0; i < str.length(); i++){
16             if(map.get(str.charAt(i)) == 1)
17                 return i;
18         }
19         return -1;
20
21     }
22 }

原文地址:https://www.cnblogs.com/wezheng/p/8418146.html

时间: 2024-11-04 09:08:34

《剑指offer》算法题第九天的相关文章

剑指offer算法总结

剑指offer算法学习总结 节选剑指offer比较经典和巧妙的一些题目,以便复习使用.一部分题目给出了完整代码,一部分题目比较简单直接给出思路.但是不保证我说的思路都是正确的,个人对算法也不是特别在行,只不过这本书的算法多看了几遍多做了几遍多了点心得体会.于是想总结一下.如果有错误也希望能指出,谢谢. 具体代码可以参考我的GitHub仓库: https://github.com/h2pl/SwordToOffer 数论和数字规律 从1到n整数中1出现的次数 题目描述 求出1~13的整数中1出现的

剑指 offer 第一题: 二维数组中的查找

打算写 图解剑指 offer 66 题 的系列文章,不知道大家有没有兴趣 ?? 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 题目分析 图 1 如果没有头绪的话,很显然使用 暴力解法 是完全可以解决该问题的. 即遍历二维数组中的每一个元素,时间复杂度:O(n^2). 其实到这里我们就可以发现,使用这种暴力解法并没有充分利用题目给出的信息.这

剑指offer链表题的双指针法总结

本篇博客旨在总结双指针法在剑指offer链表题中的应用 包括删除链表中重复的节点.链表中倒数第k个节点.链表中环的入口节点.反转链表.合并两个排序的链表.两个链表的第一个公共节点. 根据双指针的类型,可以大致分为三种: 第一种是间隔一定距离的双指针法,包括删除链表中重复的节点.链表中倒数第k个节点两题 删除链表中重复的节点 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5

剑指offer编程题Java实现——面试题12相关题大数的加法、减法、乘法问题的实现

用字符串或者数组表示大数是一种很简单有效的表示方式.在打印1到最大的n为数的问题上采用的是使用数组表示大数的方式.在相关题实现任意两个整数的加法.减法.乘法的实现中,采用字符串对大数进行表示,不过在具体的计算中,还是要将字符串转化成字符数组来进行计算. 实现两个大数的加法,要考虑到两个问题,两个数的和的位数问题,以及如何处理两个数按位相加产生的进位问题.首先两个整数相加,两个数的和的位数最多比最大的整数的位数多1:这样和的位数就确定了.对于进位问题,我的做法是先进行按位相加,相加操作完成后再按照

剑指offer编程题Java实现——面试题9斐波那契数列

题目:写一个函数,输入n,求斐波那契数列的第n项. 1 package Solution; 2 3 /** 4 * 剑指offer面试题9:斐波那契数列 5 * 题目:写一个函数,输入n,求斐波那契数列的第n项. 6 * 0, n=1 7 * 斐波那契数列定义如下:f(n)= 1, n=2 8 * f(n-1)+f(n-2), n>2 9 * @author GL 10 * 11 */ 12 public class No9Fibonacci { 13 14 public static void

剑指offer编程题Java实现——面试题7相关题用两个队列实现一个栈

剑指offer面试题7相关题目:用两个队列实现一个栈 解题思路:根据栈的先入后出和队列的先入先出的特点1.在push的时候,把元素向非空的队列内添加2.在pop的时候,把不为空的队列中的size()-1份元素poll出来,添加到另为一个为空的队列中,再把队列中最后的元素poll出来两个队列在栈不为空的情况下始终是有一个为空,另一个不为空的.push添加元素到非空的队列中,pop把非空队列的元素转移到另一个空的队列中,直到剩下最后一个元素,这个元素就是要出栈的元素(最后添加到队列中的元素). 1

剑指offer编程题Java实现——面试题14调整数组顺序使奇数位于偶数之前

题目: 输入一个整数数组,实现一个函数来调整该数组中数组的顺序,使得所有的奇数位于数组的前半部分,偶数位于数组的后半部分. 解题思路:数组中维护两个指针,第一个指针初始化时候指向数组头部,第二个指针初始化时候指向数组尾部,第一个指针指向的数字总是偶数,第二个指针指向的数字总是奇数,如果第一个指针在第二个指针之前,则交换两指针指向的元素. 1 package Solution; 2 3 /** 4 * 剑指offer面试题14:调整数组顺序是奇数位于偶数前面 5 * 题目:输入一个整数数组,实现一

剑指offer编程题Java实现——面试题10二进制中1的个数

题目: 请实现一个函数,输入一个整数,输出该整数二进制表示中1的个数.例如,把9表示成二进制是1001,有2位是1,该函数输出2解法:把整数减一和原来的数做与运算,会把该整数二进制表示中的最低位的1变成0,与运算进行多少次就有多少个1. 1 package Solution; 2 /** 3 * 剑指offer面试题10:二进制中1的个数 4 * 题目:请实现一个函数,输入一个整数,输出该整数二进制表示中1的个数. 5 * 例如,把9表示成二进制是1001,有2位是1,该函数输出2 6 * 解法

剑指offer刷题—二维数组的查找

最近接触到一本书叫做剑指offer,在这里准备在这个2个月左右将这本书刷完,当然,不需要每天多少道什么的,不在多,一天理解一道就好了,希望能成为一种习惯,另外,准备在github上也进行同步分享. 今天第一道题: 面试题3:二位数组中的查找 当我们需要解决一个复杂问题时,一个很有效的方法就是从具体的问题出手,通过分析具体的例子,得到规律. 再一个二维数组中,每一行都要按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排列.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含

剑指offer刷题记录

[TOC] 二维数组中的查找 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 解题思路:从右上角的元素进行判断,如果大于target说明这一列肯定都不是,所以将列数见一:如果小于target说明可能在下一行是等于target的,所以这一行都不是解,所以将行数加1.这样通过一个循环进行判断即可. class Solution { public: bool Find(int tar