[Easy]C++ 第一期 6道

来源:互联网 发布:小米5网络制式 编辑:程序博客网 时间:2024/05/23 05:08

400. Nth Digit

正整数列的第n位数

Find the nth digit of the infinite integer sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...

Note:
n is positive and will fit within the range of a 32-bit signed integer (n < 231).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

1 2 3 4 5 6 7 8 9 1   0   1   1   1   2

观察规律:1 ~ 9 : 1 ~ 9

10 : 9 + 2*(10 - 9)

11 : 9 + 2*(11 - 9)

12 : 9 + 2*(12 - 9)

……

99 : 9 + 2*(99 - 9)

100 : 9 + 2*90 + 3*(100 - 99)

……

999 : 9 + 2*90 + 3*(999 - 99)

1000 : 9 + 2*90 + 3*900 + 4*(1000 - 999)

……

思路:

1. 先找到当前的n对应的是几位数以及上一位数最大的n(用while循环依次累加9*cnt*10^(cnt-1))

2. 按照公式确定是哪一个数(注意减1)

3. 确定是这个数的第几位(取一个数的某一位,找到该位对应的单位整数mod ,计算n/mod%10)

程序:

class Solution {public:    int findNthDigit(int n) {        long p = 0, num = 9, plast = 0, q = 1;        int count = 1;        while(n > p){            plast = p;            p = p + num*count;            count++;            num *= 10;            q *= 10;        }        q /= 10; count -= 1;         long start = q + (n - plast - 1)/count;        int pos = (n - plast - 1)%count;        long mod = 1;        int len = count;        for (int i = 1; i < len - pos; i++, mod *= 10);        int result = start/mod%10;        return result;    }};

运行结果:
Accepted    0ms    90.13%

————————————————————————

67. Add Binary

两个二进制字符串相加

Given two binary strings, return their sum (also a binary string).

For example,
a = "11"
b = "1"
Return "100".

思路1:将两个二进制数转化为十进制分别相加,再转为二进制字符串

注意:输入为"0"的情况

程序:

class Solution {public:    string addBinary(string a, string b) {        int alen = a.length();        int blen = b.length();        long num = 0;        for(int i = 0; i < alen; i++)            num += (a[alen - 1 - i] - '0')*pow(2, i);        for(int i = 0; i < blen; i++)            num += (b[blen - 1 - i] - '0')*pow(2, i);        int len = 0;        for (int i = 1; i <= num; i *= 2, len += 1) ;        if (!num) len = 1;        string result(len, '0');        for (int i = 1; i <= len; i++){            result[len-i] += num%2;            num /= 2;        }        return result;       }};

运行结果:

Wrong Answer 

失败原因:字符串保存的二进制数位数可能远远超过任何类型允许的位数


思路2:分别按位相加

注意:

1.字符串存储二进制数的方式与正常相反,为从高到低,需要先找到各自的长度

2.由于一位上的相加只有四种结果,0 1 2 3 可以直接在result上操作,由sum/2和sum%=2可分别获得该位和进位

程序:

class Solution {public:    string addBinary(string a, string b) {        int alen = a.length();        int blen = b.length();        int len = alen > blen ? alen : blen;        string result(len,'0');        int carry = 0;        for(int i = 1; i <= len; i++){            int sum = carry;            if(alen - i >= 0) sum += a[alen-i] - '0';            if(blen - i >= 0) sum += b[blen-i] - '0';            carry = sum / 2;            sum %= 2;            result[len-i] += sum;        }        if (carry == 1)            result = "1" + result;        return result;     }};

运行结果:

Accepted     3ms     28.41%

————————————————————


66. Plus One

按位保存的非负整数加一

Given a non-negative integer represented as a non-empty array of digits, plus one to the integer.

You may assume the integer do not contain any leading zero, except the number 0 itself.

The digits are stored such that the most significant digit is at the head of the list.

注意vector操作

程序:

class Solution {public:    vector<int> plusOne(vector<int>& digits) {        for(int i=digits.size()-1; i>=0; i--){            if (digits[i] != 9){                digits[i] ++;                break;            }            else{                digits[i] = 0;            }        }                if(digits[0] == 0){            vector<int> result(digits.size()+1);            result[0] = 1;            for(int i=digits.size()-1; i!=0; i--){                result[i+1] = digits[i];            }            return result;                    }else return digits;           }};

运行结果:

Accepted     3ms     16.30%

疑问:如果输入是以0开头的这种恶心东西怎么办

——————————————————


1. Two Sum

从数组中寻找和为特定目标的数

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

思路1:两层循环搜索(注意vector用法)

程序:

class Solution {public:    vector<int> twoSum(vector<int>& nums, int target) {        vector<int> result(2);        bool flag = false;        for(int i = 0; i < nums.size() - 1; i++){            if (flag) break;            for(int j = i + 1; j < nums.size(); j++)                if (nums[i] + nums[j] == target){                    result[0] = i;                    result[1] = j;                    flag = true;                    break;                }        }        return result;    }};

运行结果:

Accepted     136ms     28.87%

失败原因:复杂度为O(n^2)


思路2:先排序,然后再搜索,排序复杂度为O(nlogn),排序后搜索为O(n)

1. C++自带快速排序函数sort(虽然还是要会自己写)

2. 注意先将数组备份再排序

3. 搜索时分别从头尾开始,按照与target的大小关系前后移动(一定找得到!)

4. 最后为标准输出必须做一步判断大小和交换(这里又是教科书式的按位异或)

程序:

class Solution {public:    vector<int> twoSum(vector<int>& nums, int target) {        vector<int> result;        vector<int> numsCopy;        for(int i = 0; i < nums.size(); i++) numsCopy.push_back(nums[i]);        sort(numsCopy.begin(), numsCopy.end());        vector<int> tmp;        int begin = 0, end = numsCopy.size() - 1;        while(begin < end){            int y = numsCopy[begin] + numsCopy[end];            if (y == target){                tmp.push_back(numsCopy[begin]);                tmp.push_back(numsCopy[end]);                break;            }else if(y > target) end--;            else begin++;        }        for(int i = 0; i < nums.size(); i++)            if(nums[i] == tmp[0]){                result.push_back(i);                break;            }        for(int i = nums.size() - 1; i >= 0; i--)            if(nums[i] == tmp[1]){                result.push_back(i);                break;            }        if (result[0] > result[1]){            result[0] = result[0]^result[1];            result[1] = result[0]^result[1];            result[0] = result[0]^result[1];        }        return result;    }};

运行结果:
Accepted     6ms     84.44%

思路3:建立哈希查找表,复杂度为O(n)
1. 开始的思路是先遍历数组,建立一个哈希查找表,然后遍历数组的每个数去找与target的差是否出现
2. 改进版的思路是直接遍历数组,如果哈希表里没有与target的差就把该数加进查找表
3.C++自带map库
程序:

class Solution {public:    vector<int> twoSum(vector<int>& nums, int target) {        vector<int> result;        map<int, int> finder;        for(int i = 0; i < nums.size(); i++){            if (finder.count(nums[i]) != 0){                result.push_back(finder[nums[i]]);                result.push_back(i);                break;            }            finder[target - nums[i]] = i;        }        return result;    }};
运行结果:
Accepted     13ms     44.45%

————————————————


167. Two Sum II

从排序好的数组中寻找和为特定目标的数

Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution and you may not use the same element twice.

Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2

思路:上一题的简化版

程序:

class Solution {public:    vector<int> twoSum(vector<int>& numbers, int target) {        vector<int> result;        int begin = 0, end = numbers.size() - 1;        while(begin < end){            int y = numbers[begin] + numbers[end];            if (y == target){                result.push_back(begin + 1);                result.push_back(end + 1);                break;            }else if(y > target) end--;            else begin++;        }        return result;    }};

运行结果:

Accepted     6ms     24.95%

————————————————


88. Merge Sorted Array 

交换排序好的数组

Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.

Note:
You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2. The number of elements initialized in nums1 and nums2 are m and n respectively.


难点:题目输入的数组个数可能与所给数组的大小不符,也可能为0

思路1:将数组2中的数依次在数组1中搜索,找到它们所在的位置并插入

1. 这么做首先要判断数组1是否为空

2. 然后要将数组1中的元素剪短至题目要求

3. 每次搜索不超过数组1的大小

程序:

class Solution {public:    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {        if (m == 0){            nums1 = nums2;            return;        }        vector<int> nums;        for(int i = 0; i < m; i++){            nums.push_back(nums1[i]);        }        nums1 = nums;        int pos = 0;        for(int i = 0; i < n; ++i){            while(nums1[pos] < nums2[i] && pos < nums1.size())                pos++;            nums1.insert(nums1.begin() + pos, nums2[i]);        }    }};
运行结果:

Accepted     3ms     55.75%


思路2:构造一个新数组,从两个数组的低位开始检索

1. 这样可以直接避免某一数组为0的情况,代价是多一步数组复制

2. 合理使用++


思路3:将比较的结果直接保存在数组1中

1.为避免重复,这次必须从高位开始比较

2.首先应该将m和n分别减1

程序:

class Solution {public:    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {        m -= 1;        n -= 1;        int i = m + n + 1;        while(m >= 0 || n >= 0){            if (m < 0)                nums1[i--] = nums2[n--];            else if (n < 0)                nums1[i--] = nums1[m--];            else                nums1[i--] = nums1[m] > nums2[n] ? nums1[m--] : nums2[n--];        }    }};
运行结果:

Accepted     3ms     55.75%

原创粉丝点击