[Google interview questions] Two ideas for finding the number of occurrences of 1 in positive numbers from 1 to n and their complexity analysis

Description of the problem:

Input an integer n, find the number of occurrences of 1 in the decimal representation of n integers from 1 to n. For example, if you enter 12, the numbers including 1 in the integers from 1 to 12 are 1. 10. 11 and 12. 1 appear a total of 5 times.

This is a widely circulated google interview question.

algorithm:

The first idea : Count each number from 1 to n, and add the results of the statistics. Algorithm complexity is O(n)

Another way of thinking : give an example.

Let n=321. but:

The form of 1 in the one's place is XY1, and the sum of the times is 33 (because the possible combination of the ten's place and the hundreds place is 0-32)

The sum of the number of occurrences of 1 in the tens place is more complex, in the form of X1Y, and the value range of X is 0-3. The value range of Y is 0-9. Therefore, X1Y has a common form of 40, that is, the sum of the number of occurrences of 1 in the tens place is 40

Its hundreds place appears in the form of 1XY. Obviously, the value range of XY is 00-99. So the sum of times is 100

So the sum is 100+40+33=173

After analysis, we can get a general formula:

For a digit number n, the sum of the number of occurrences of 1 on the i-th digit from the right (i starts from 0) is: (the number of combinations from i+1 digits to digit-1 digits + 1)*10 to the power of i

Mathematically expressed as

count(i)=[n/pow(10,i+1)+1]*pow(10,i)

sum=∑count(i)

Since the number of digits digit=[logn]+1 (where logn is rounded down), the time complexity is O(logn)

Code:

The first idea:

#pragma once
#include<iostream>
using namespace std;

int Find(int m)
{
	int sum = 0;
	while (m > 0)
	{
		int temp;
		temp = m % 10;
		if (temp == 1)
			sum += 1;
		m = m / 10;
	}
	return sum;
}

int Count(int n)
{
	int sum = 0;
	for (int i = 1; i <= n; i++)
		sum += Find(i);
	return sum;
}

void  main()
{
	int n;
	cin >> n;
	Count(n);
	cout << Count(n) << endl;
	system("pause");
}

Another way of thinking:

#pragma once
#include<iostream>
#include"math.h"
using namespace std;

int Count(int list[], int n,int digit)
{
	int sum = 0;
	for (int i = 0; i < digit; i++)
		sum += (int(n / pow(10, i + 1)) + 1)*(int)pow(10, i);
	return sum;
}

void  main()
{
	int n;
	cin >> n;
	int temp = n;
	int digit = 1; // n digits
	while (temp > 0)
	{
		if (temp - temp % 10 > 0)
			digit++;
		temp = temp / 10;
	}
	int* list = new int[digit];//list[i] is the number of n from the i-th digit on the right
	for (int i = 0; i < digit; i++)
		list[i] = (n - int(n%(int)pow(10, i))) / (int)pow(10, i) % 10;
	cout << Count(list, n,digit) << endl;
	system("pause");
}


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326366976&siteId=291194637