[Easy]C++ 第一期 6道

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%

### 回答1: 可以通过使用curl_easy_setopt函数来设置输出处理函数,具体的语法为:curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_data); 其中 write_data 是输出处理函数的名称。 ### 回答2: 在使用cURL库中的curl_easy_setopt函数时,可以通过设置输出处理函数来处理cURL执行操作的输出。设置输出处理函数的步骤如下: 1. 创建一个用于处理输出的函数。 这个函数的格式必须符合以下原型: size_t handle_output(void *ptr, size_t size, size_t nmemb, void *userdata); 函数的参数依次为ptr,size,nmemb和userdata。其中,ptr是接收到的数据指针,size是每个数据项的大小,nmemb是接收到的数据项数目,userdata是一个用户指定的指针,可用于传递自定义数据。 2. 在代码中定义代表cURL会话的CURL类型的变量,并通过curl_easy_init函数进行初始化。 3. 调用curl_easy_setopt函数,并将设置项设为CURLOPT_WRITEFUNCTION,第二个参数为输出处理函数的指针。 4. 如果需要传递自定义数据给输出处理函数,则还可以使用curl_easy_setopt函数设置CURLOPT_WRITEDATA选项,第二个参数为自定义数据的指针。 5. 执行需要的cURL操作,如发送HTTP请求。 下面是一个简单的示例代码,演示如何设置输出处理函数: ```c #include <stdio.h> #include <curl/curl.h> size_t handle_output(void *ptr, size_t size, size_t nmemb, void *userdata) { // 处理接收到的数据 // ptr是接收到的数据指针,size是每个数据项的大小,nmemb是接收到的数据项数目,userdata是自定义数据指针 // 示例代码中,直接打印接收到的数据到控制台 size_t total_size = size * nmemb; fwrite(ptr, 1, total_size, stdout); return total_size; } int main() { CURL *curl; curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl, CURLOPT_URL, "http://www.example.com"); // 设置请求的URL curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handle_output); // 设置输出处理函数 // 可选:设置自定义数据指针 // curl_easy_setopt(curl, CURLOPT_WRITEDATA, custom_data_ptr); CURLcode res = curl_easy_perform(curl); // 执行请求操作 if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_easy_cleanup(curl); } return 0; } ``` 以上是设置curl_easy_setopt的输出处理函数的简要步骤和示例代码。根据需要,可以在输出处理函数中自定义处理接收到的数据。 ### 回答3: curl_easy_setopt函数是libcurl库中用于设置选项的函数,可以通过该函数设置curl的各种行为和选项。其中一个常见的选项是设置输出处理函数,即设置curl用于处理响应数据的回调函数。 要设置curl的输出处理函数,需要使用curl_easy_setopt函数,并将选项参数设置为CURLOPT_WRITEFUNCTION,然后将回调函数作为参数传递给该选项。 具体的代码如下所示: ``` // 声明输出处理函数,需要符合curl_write_callback类型的定义 size_t writeCallback(char* ptr, size_t size, size_t nmemb, void* userdata) { // 在这里对收到的数据进行处理 // ptr:收到的数据指针 // size:每个数据元素的大小 // nmemb:数据元素的数量 // userdata:用户自定义数据指针 // 返回值表示实际处理的字节数 } // 初始化curl CURL* curl = curl_easy_init(); if(curl) { // 设置输出处理函数 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback); // 这里可以继续设置其他选项... // 执行curl请求 CURLcode res = curl_easy_perform(curl); if(res != CURLE_OK) { // 请求失败的处理逻辑... } // 清理curl curl_easy_cleanup(curl); } ``` 在上述代码中,通过curl_easy_setopt函数将选项参数设置为CURLOPT_WRITEFUNCTION,并将回调函数writeCallback作为参数传递。在writeCallback回调函数中,可以对收到的响应数据进行处理。在函数内部,可以通过参数ptr、size和nmemb访问到接收到的数据。需要注意,writeCallback回调函数的返回值需要表示实际处理的字节数。 通过这种方式,我们可以自定义输出处理函数来处理curl接收到的响应数据,实现自己的数据处理逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值