剑指offer(31-35)编程题
31.求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。
class Solution { public: int NumberOf1Between1AndN_Solution(int n) { string str = std::to_string(n); int len = str.length(); int first = str[0] - '0'; if (len == 1 && first == 0) return 0; if (len == 1 && first > 0) return 1;; //最高为1 int num1 = 0; if (first > 1) { num1 = pow(10, len - 1); } else if(first == 1){ num1 = stoi(str.substr(1)) + 1; } int num2 = first * (len - 1) * pow(10, len - 2); return num1 + num2 + NumberOf1Between1AndN_Solution(stoi(str.substr(1))); } };
32.输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
class Solution { public: static bool comp(const string& a, const string& b) { string ab = a + b; string ba = b + a; if(ab > ba) return false; return true; } public: string PrintMinNumber(vector<int>& numbers) { vector<string> numStrs; for(size_t i=0;i<numbers.size();i++){ numStrs.push_back(to_string(numbers[i])); } sort(numStrs.begin(),numStrs.end(),comp); string res; for(int i=0;i<numStrs.size();i++){ res += numStrs[i]; } return res; } };
33把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
1 class Solution { 2 public: 3 int GetUglyNumber_Solution(int index) { 4 vector<int> uglyArray = { 1, 2, 3, 4, 5 }; 5 if (index <= 5) 6 return uglyArray[index - 1]; 7 8 int m2, m3, m5; 9 int n1 = 1,n3 = 1,n5 = 1; 10 int k = 6; 11 while (k <= index) { 12 for (int i = n1; i < uglyArray.size(); i++) { 13 if (2 * uglyArray[i] > uglyArray.back()) { 14 m2 = 2 * uglyArray[i]; 15 n1 = i; 16 break; 17 } 18 } 19 for (int i = n3; i < uglyArray.size(); i++) { 20 if (3 * uglyArray[i] > uglyArray.back()) { 21 m3 = 3 * uglyArray[i]; 22 n3 = i; 23 break; 24 } 25 } 26 for (int i = n5; i < uglyArray.size(); i++) { 27 if (5 * uglyArray[i] > uglyArray.back()) { 28 m5 = 5 * uglyArray[i]; 29 n3 = i; 30 break; 31 } 32 } 33 uglyArray.push_back(min(min(m2,m3),m5)); 34 k++; 35 } 36 return uglyArray.back(); 37 } 38 };
34.在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置。如果字符串为空,返回-1
1 class Solution { 2 public: 3 int FirstNotRepeatingChar(string str) { 4 int tableSize = 256; 5 int *hashTable = new int[tableSize]; 6 for (int i = 0; i < 256; i++) { 7 hashTable[i] = 0; 8 } 9 for (size_t i = 0; i < str.size(); i++) { 10 hashTable[static_cast<unsigned int>(str[i])]++; 11 } 12 13 for (size_t i = 0; i < str.size(); i++) { 14 if (hashTable[static_cast<unsigned int>(str[i])] == 1) 15 return i; 16 } 17 18 delete[] hashTable; 19 return -1; 20 } 21 };
35.在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
1 class Solution { 2 private: 3 int InversePairs(vector<int>&data, int left, int right) { 4 if (left == right) return 0; 5 int mid = left + (right - left) / 2; 6 int leftCount = InversePairs(data, left, mid); 7 int rightCount = InversePairs(data, mid + 1, right); 8 int mergeCount = merge(data, left, mid, right); 9 return (leftCount + rightCount + mergeCount)%1000000007; 10 } 11 12 int merge(vector<int>& data, int left, int mid, int right) { 13 int* temp = new int[right - left + 1]; 14 int p = mid; 15 int q = right; 16 int count = 0; 17 int k = right - left; 18 while (p >= left && q > mid) { 19 if (data[p] > data[q]) { 20 count = (count + q - mid)%1000000007; 21 temp[k--] = data[p--]; 22 } else { 23 temp[k--] = data[q--]; 24 } 25 } 26 while (p >= left) { 27 temp[k--] = data[p--]; 28 } 29 while (q > mid) { 30 temp[k--] = data[q--]; 31 } 32 for (int i = 0; i <= right - left; i++) { 33 data[left + i] = temp[i]; 34 } 35 delete[] temp; 36 return count; 37 } 38 public: 39 int InversePairs(vector<int> data) { 40 int n = data.size(); 41 if (n < 2) 42 return -1; 43 return InversePairs(data, 0, n - 1); 44 } 45 };