31、剑指offer–整数中1出现的次数(从1到n整数中1出现的次数)
题目描述:
求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。
思路1:
如:30143:
由于3>1,则个位上出现1的次数为(3014+1)*1
由于4>1,则十位上出现1的次数为(301+1)*10
由于1=1,则百位上出现1次数为(30+0)*100+(43+1)
由于0<1,则千位上出现1次数为(3+0)*1000
注:以百位为例,百位出现1为100~199,100的意思为单步出现了100~199,100次,30是因为出现了30次100~199,+(43+1)是因为左后一次301不完整导致。
如果第i位上的数字为0,则第i位可能出现1的次数由其高位决定,若没有高位,则视为0,此时第i位可能出现1的次数为:其高位数*10^(i-1),例如若c为0,则次数为ab*10^2;
如果第i位上的数字为1,则第i位上可能出现1的次数受其高位和低位影响,若没有,则视为0,此时第i位可能出现1的次数:其高位数*10^(i-1)+(低位数+1),例如若c为1,则次数为ab*10^2+(de+1);
如果第i位上的数字大于1,则第i位上可能出现1的次数受其高位影响,若没有,则视为0,此时第i位可能出现1的次数:(其高位数+1)*10^(i-1),例如若c大于1,则次数为(ab+1)*10^2;
思路2:
暴力解决。
代码:
//1、
function NumberOf1Between1AndN_Solution(n)
{
if(n < 0) return 0;
var high = n, low, cur, tem, count = 0, i = 1;
while(high != 0){
high = parseInt(n / Math.pow(10,i));
tem = n % Math.pow(10,i);
cur = parseInt(tem / Math.pow(10,i-1));
low = tem % Math.pow(10,i - 1);
if(cur == 1){
count += high * Math.pow(10,i-1) + low + 1;
}else if(cur == 0){
count += high * Math.pow(10,i-1);
}else{
count += (high + 1) * Math.pow(10,i-1);
}
i++;
}
return count;
}
//2、
function NumberOf1Between1AndN_Solution(n)
{
if(n < 0) return 0;
var count = 0;
for(var i = 1 ; i <= n ; i++){
var number = i;
while(number > 0){
if(number % 10 == 1){
count++;
}
number = Math.floor(number/10);
}
}
return count;
}
32、剑指offer–把数组排成最小的数
题目描述:
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
思路:
排序规则如下:
若ab > ba 则 a > b,
若ab < ba 则 a < b,
若ab = ba 则 a = b;
然后从小到大拼接即为所求结果
代码:
function PrintMinNumber(numbers)
{
numbers.sort(function(a,b){
var s1 = a + "" + b;
var s2 = b + "" + a;
for(var i = 0 ; i < s1.length ; i++){
if(s1.charAt(i) > s2.charAt(i)){
return 1;
}else if(s1.charAt(i) < s2.charAt(i)){
return -1;
}
}
return 1;
})
var result = "";
numbers.forEach(function(item){
result = result.concat(item);
})
return result;
}
33、剑指offer–丑数
题目描述:
把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
思路:
下一个丑数是由数组中某个丑数A * 2,B * 3,C * 5中的最小值得来的。
代码:
function GetUglyNumber_Solution(index)
{
// write code here
if(index == 0) return 0;
var ugly = [1];
var factor2 = 0, factor3 = 0, factor5 = 0;
for(var i = 1 ; i < index ; i++){
ugly[i] = Math.min(ugly[factor2] * 2 , ugly[factor3] * 3 , ugly[factor5] * 5);
if(ugly[i] == ugly[factor2] * 2) factor2++;
if(ugly[i] == ugly[factor3] * 3) factor3++;
if(ugly[i] == ugly[factor5] * 5) factor5++;
}
return ugly[index - 1];
}
34、剑指offer–第一个只出现一次的字符
题目描述:
在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置
思路:
使用map结构,将每次出现字符和出现次数放入map中。
代码:
function FirstNotRepeatingChar(str)
{
var map = {};
var strArr = str.split('');
strArr.forEach(function(item){
if(!map[item]){
map[item] = 1;
}else{
map[item]++;
}
});
for(var i = 0 ; i < str.length ; i++){
if(map[str[i]] == 1){
return i;
}
}
return -1;
}
35、剑指offer–数组中的逆序对
题目描述:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
思路:
利用归并排序思想,先求出每个组中逆序对数,然后合并、排序并统计.
代码:
function InversePairs(data)
{
if(!data || data.length < 0) return 0;
var count = 0;
var copy = data.slice();
count = mergeSort(data,copy,0,data.length-1);
return count%1000000007;
}
function mergeSort(data,copy,start,end){
if(start === end) return 0;
var mid = (end - start) >> 1,
left = mergeSort(copy,data,start,start + mid),
right = mergeSort(copy,data,start+mid+1,end),
count = 0,
p = start+mid,//前一个数组的最后一个下标
q = end,//后一个数组的下标
copyIndex = end;//辅助数组下标,从最后一个算起
while(p >= start && q >= start+mid+1){
if(data[p]>data[q]){
count += q-start-mid;
copy[copyIndex--] = data[p--];
}else{
copy[copyIndex--] = data[q--];
}
}
while(p >= start){
copy[copyIndex--] = data[p--];
}
while(q >= start+mid+1){
copy[copyIndex--] = data[q--];
}
return count + left + right;
}
36、剑指offer–两个链表的第一个公共结点
题目描述:
输入两个链表,找出它们的第一个公共结点。
思路:
两个指针,遍历后比较结点的值
代码:
function FindFirstCommonNode(pHead1, pHead2)
{
var p1 = pHead1;
var p2 = pHead2;
while(p1 != p2){
p1 = (p1 == null) ? pHead2 : p1.next;
p2 = (p2 == null) ? pHead1 : p2.next;
}
return p1;
}
剑指Offer每日6题(JavaScript版)-系列文章参考专栏:JavaScript版剑指offer