• C编程题总结


    最大子序列和:

    给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

    示例:

    输入: [-2,1,-3,4,-1,2,1,-5,4],
    输出: 6
    解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

    int maxSubArray(int* nums, int numsSize){
    
    int i = 0;
    int sum=nums[0];
    int summax = nums[0];
    for(i = 1; i < numsSize;i++)
    {
       if((nums[i]>sum)&&(sum<0)) {
           sum = nums[i];
       }
        else{
            sum+=nums[i];
        }
       // printf("sum=%d,nums[i]=%d
    ",sum,nums[i]);
        if(summax < sum){
            summax=sum;
        }
    }
    
    return summax;
    }

    报数序列:

    是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:

    1. 1
    2. 11
    3. 21
    4. 1211
    5. 111221
    1 被读作  "one 1"  ("一个一") , 即 11。
    11 被读作 "two 1s" ("两个一"), 即 21。
    21 被读作 "one 2",  "one 1" ("一个二" ,  "一个一") , 即 1211。

    给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。

    注意:整数顺序将表示为一个字符串。

    示例 1:

    输入: 1
    输出: "1"
    示例 2:

    输入: 4
    输出: "1211"

    #define Len 4500
    char * countAndSay(int n){
        char *pre, *num;
        int i=1;
        int len=0;
        int m=0;
        char flag;
        int index=0;
        pre = (char *)malloc(sizeof(char) * Len);//保存当前字符串
        num = (char *)malloc(sizeof(char) * Len);//保存上一层字符串 
        if(n==1)
            return "1";
        else
        {
            num=countAndSay(n-1);//求出上一层字符串
            len=strlen(num);//求出上一层字符串长度
            flag=num[0];//标记字符为第一个字符
            m=1;//记录标记字符的个数
            while(i<len)//向后遍历
            {
                if(num[i]==flag)//如果当前字符和标记字符一样
                    m+=1;//个数加一
                else//如果当前字符和标记字符不一样
                {
                    pre[index++]=m+'0';//将此次遍历结果写入结果字符串中
                    pre[index++]=flag;
                    m=1;//修改个数
                    flag=num[i];//修改标记字符为当前字符
                }
                i+=1;
           }
           pre[index++]=m+'0';//将最后一次遍历结果写入字符串中
           pre[index++]=flag;
           pre[index]='';
           return pre;
        }
    }

    搜索插入位置:

    给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

    你可以假设数组中无重复元素。

    示例 1:

    输入: [1,3,5,6], 5
    输出: 2
    示例 2:

    输入: [1,3,5,6], 2
    输出: 1

    int searchInsert(int* nums, int numsSize, int target){
       int left=0;
       int right=numsSize-1;
        int mid;
        while(left<=right){//二分法
            mid=left+((right-left)>>1);
            if(nums[mid]==target) return mid;
            else if(nums[mid]>target) right=mid-1;//注意+-1
            else if(nums[mid]<target) left=mid+1;
        }
        if(target<nums[mid]) return mid;//此时target位于mid附近
        else return mid+1;
    }

    实现 strStr() 函数:

    给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回  -1。

    示例 1:

    输入: haystack = "hello", needle = "ll"
    输出: 2
    示例 2:

    输入: haystack = "aaaaa", needle = "bba"
    输出: -1

    int strStr(char * haystack, char * needle){
        int a=strlen(haystack);
        int b=strlen(needle);
        char *p=NULL;//定义一个新指针
        if(b==0) return 0;//这里多考虑a,b同时或不同时为0的情况
        p=haystack;
        for(int i=0;i<=a-b;++i){//注意a-b
            if(haystack[i]==needle[0]){
                if(!strncmp(p,needle,b)) return i;//注意strcmp在这里不可以使用,他只有两个参数
            }
            ++p;
        }
        return -1;
    }

    两数之和:

    给定 nums = [2, 7, 11, 15], target = 9

    因为 nums[0] + nums[1] = 2 + 7 = 9
    所以返回 [0, 1]

    int* twoSum(int* nums, int numsSize, int target, int* returnSize){//参数:原始数组,原始数组长度,比较值,返回数组长度
        int* res=(int*)malloc(sizeof(int)*2);
        *returnSize=0;
        int i,j;
        for(i=0;i<numsSize-1;i++)
        {
            for(j=i+1;j<numsSize;j++)//依次往后比较
            {
                if(nums[i]+nums[j]==target)
                {
                    res[0]=i;
                    res[1]=j;
                    *returnSize=2;
                    return res;
                }
            }
        }
        return res;
    }

    存在重复元素:

    输入: [1,2,3,1]输出: true

    输入: [1,2,3,4]输出: false

    void swap(int *a, int *b)//自己编写交换函数
    {
        int temp;
        temp = *a;
        *a = *b;
        *b = temp;
    }
    void quickSort(int arr[] ,int start, int end)//自己编写归并排序
    {
        int arrBase, arrMiddle;
    
        int tempStart = start,
            tempEnd = end;
    
        //对于这种递归的函数,内部必须要有一个函数返回的条件
        if(tempStart >= tempEnd)
            return;
    
        //拷贝一个基准值作为后面比较的参数
        arrBase = arr[start];
        while(start < end)
        {
            while(start < end && arr[end] > arrBase)
                end--;
            if(start < end)
            {
                swap(&arr[start], &arr[end]);
                start++;
            }
    
            while(start < end && arr[start] < arrBase)
                start++;
            if(start < end)
            {
                swap(&arr[start], &arr[end]);
                end--;
            }
        }
        arr[start] = arrBase;
        arrMiddle = start;
    
        //分治方法进行递归
        quickSort(arr,tempStart,arrMiddle-1);
        quickSort(arr,arrMiddle+1,tempEnd);
    }
    int comp(const void *a,const void *b){//自己编写比较函数
        return (*(int*)a > *(int*)b);
    }
    bool containsDuplicate(int* nums, int numsSize){
        qsort(nums, numsSize, sizeof(int), comp);//把原始数组的值,按顺序排序
        for(int k=0;k<numsSize-1;k++){//判断,相邻元素有相等,则返回true。
            if(nums[k]==nums[k+1]){
                return true;
            }
        }
        return false;
    }

    两数相加:

    输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)

    输出:7 -> 0 -> 8

    原因:342 + 465 = 807

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     struct ListNode *next;
     * };
     */
    //链表结构
    struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) 
    {
        //初始化空头
        struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
        head->next =NULL;
        struct ListNode* tail;
        tail = head;
        struct ListNode* p1 = l1;
        struct ListNode* p2 = l2;
    
        int carry = 0; //进位
       if(p1==NULL) return p2;
       if(p2==NULL) return p1;
    //循环,直到跳出两个链表 //当两条链表一样长时只需这一次处理,但是当不一样长时,只能处理一样长的大小 while (p1 != NULL && p2 != NULL) { //当前结点的和,注意加上进位 int sum = p1->val + p2->val + carry; //当前结点和大于等于10时 if (sum >= 10) { sum -= 10; //当前结点的值-10,变为个位 carry = 1; //大于10,进位1 } else { carry = 0; } //初始化结点,尾添加, 必须先将尾指针移动到新的尾结点上再赋值,因为不这么做的话,第一个结点无法正确赋值(因为这时候尾指针还没有真正移到第一个结点上,此时指向的还是头结点) tail->next = (struct ListNode*)malloc(sizeof(struct ListNode)); tail = tail->next; tail->val = sum; p1 = p1->next; p2 = p2->next; } //当两条链表不一样长时,其中一者为NULL了,另一者还没完,这时候用p1指向没完的那一条链表,继续遍历 if (p1 == NULL) { p1 = p2; } else if (p2 = NULL) { p1 = p1; } //遍历剩余部分 while (p1 != NULL) { int sum = p1->val + carry; //带上进制计算当前结点和 if (sum >= 10) { sum -= 10; carry = 1; } else { carry = 0; } //继续朝合并的链表中添加结点 tail->next = (struct ListNode*)malloc(sizeof(struct ListNode)); tail = tail->next; tail->val = sum; p1 = p1->next; } //如果最后一位还有进制,再申请一个结点存1 if (carry == 1) { tail->next = (struct ListNode*)malloc(sizeof(struct ListNode)); tail = tail->next; tail->val = 1; } tail->next = NULL; //尾指针赋空,结尾 //因为我们不能返回头结点,所以要把头结点释放了,但是要头指针移到第一个结点 struct ListNode* pTemp = head; head = head->next; free(pTemp); return head; }

    整数反转:

    输入: 123
    输出: 321
    输入: -123
    输出: -321
    输入: 120
    输出: 21
    int reverse(int x)
    {
        int temp;
        int i;
        long c=0;//定义为long型
        for(i=0;i<10;++i){
            temp=x%10;//取出最后一位包括负数情况
            x=x/10;
            c=c*10+temp;
            if(c>0x7fffffff||c<(signed int)0x80000000){//判断整型数据是否溢出
                return 0;
            }
            if(x==0) break;
        }
        return c;
    }

    罗马数转整数:

    字符 数值
    I 1
    V 5
    X 10
    L 50
    C 100
    D 500
    M 1000

    特殊的规则只适用于以下六种情况:

    I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
    X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 
    C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

    int romanToInt(char * s){
        int len=strlen(s);
        if(len==0) return 0;
        int num=0;
        for(int i=0;i<len;++i){
            switch(s[i]){//判断每一位字符
                case 'M':num+=1000;break;
                case 'D':num+=500;break;
                case 'C':num+=100;if(i<len-1) if(s[i+1]=='D'||s[i+1]=='M') num-=200;break;//特殊情况,特殊处理,第一个if保证罗马数不是个位数字
                case 'L':num+=50;break;
                case 'X':num+=10;if(i<len-1) if(s[i+1]=='L'||s[i+1]=='C') num-=20;break;
                case 'V':num+=5;break;
                case 'I':num+=1;if(i<len-1) if(s[i+1]=='V'||s[i+1]=='X') num-=2;break;
            }
        }
        return num;
    }

    查找字符串数组中的最长公共前缀

    如果不存在公共前缀,返回空字符串 ""。

    示例 1:

    输入: ["flower","flow","flight"]
    输出: "fl"
    示例 2:

    输入: ["dog","racecar","car"]
    输出: ""
    解释: 输入不存在公共前缀。
    说明:

    所有输入只包含小写字母 a-z 。

    char * longestCommonPrefix(char ** strs, int strsSize){
        if(strsSize==0){
            char *a=(char *)malloc(1);
            a[0]='';
            return a;
        }
        if(strsSize==1){
            return strs[0];
        }
      //首先判断两种特殊情况
    int is = 1 , temp ; int i=0; for(;is;++i){ temp = strs[0][i]; for(int j=0;j<strsSize;++j){ if((!strs[j][i])||strs[j][i]!=temp){ is = 0; break; } } } strs[0][i-1]=''; return strs[0]; }

    有效的括号:

    注意空字符串可被认为是有效字符串。

    示例 1:

    输入: "()"
    输出: true
    示例 2:

    输入: "()[]{}"
    输出: true
    示例 3:

    输入: "(]"
    输出: false
    示例 4:

    输入: "([)]"
    输出: false
    示例 5:

    输入: "{[]}"
    输出: true

    bool isValid(char * s){
        if ( s == NULL || s[0] == '' ) return true;//判断为空情况
        char *aus = (char *) malloc (strlen(s) + 1);
        int top = 0;
        for(int i=0;i<strlen(s);++i){
            if(s[i]=='('||s[i]=='{'||s[i]=='[') aus[top++]=s[i];//模拟入栈操作
            else{
                if(--top<0) return false;//模拟出栈操作
                if(s[i]==')'&&aus[top]!='(') return false;
                if(s[i]==']'&&aus[top]!='[') return false;
                if(s[i]=='}'&&aus[top]!='{') return false;
            }
        }
        return !top;//初值为0,入栈多少次,出栈就多少次,最后依然为0。
    }

    回文数判断:

    是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

    示例 1:

    输入: 121
    输出: true
    示例 2:

    输入: -121
    输出: false
    解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
    示例 3:

    输入: 10
    输出: false
    解释: 从右向左读, 为 01 。因此它不是一个回文数。

    bool isPalindrome(int x){
        if(x<0) return false;
        if(x==0) return true;
        int a;
        long b=0,y=x;//定义为long型
        while(y>=1){
            a=y%10;
            y=y/10;
            b=b*10+a;
        }
        if(x==b) return true;
        return false;
    }

    合并两个有序链表:

    将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

    示例:

    输入:1->2->4, 1->3->4
    输出:1->1->2->3->4->4

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     struct ListNode *next;
     * };
     */
    //链表结构
    struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
        if(l1==NULL) return l2;
        if(l2==NULL) return l1;//首先判断为空指针情况
        struct ListNode* l;
        struct ListNode* j;
        if(l1->val<l2->val){
            l=l1;
            l1=l1->next;
        }
        else{
            l=l2;
            l2=l2->next;
        }//先定义一个首节点
        j=l;
        while(l1&&l2){
            if(l1->val<l2->val){
                j->next=l1;//注意指针的值比较和赋值的区别
                l1=l1->next;
            }
            else{
                j->next=l2;
                l2=l2->next;
            }
            j=j->next;//指针后移操作
        }
        if(l1){//有剩余情况
            j->next=l1;
        }
        if(l2){
            j->next=l2;
        }
        return l;
    }

    删除排序数组的重复项:

    给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

    不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

    示例 1:

    给定数组 nums = [1,1,2],

    函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。

    你不需要考虑数组中超出新长度后面的元素。

    int removeDuplicates(int* nums, int numsSize){
        if(numsSize==0||numsSize==1) return numsSize;
        int len=0;
        for(int i=0;i<numsSize-1;++i){
            if(nums[i]!=nums[i+1]){//有序数组相邻比较
                nums[len++]=nums[i];
            }
        }
        nums[len++]=nums[numsSize-1];
        return len;
    }

    移除元素:

    给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。

    不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

    元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

    示例 1:

    给定 nums = [3,2,2,3], val = 3,

    函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。

    你不需要考虑数组中超出新长度后面的元素。

    int removeElement(int* nums, int numsSize, int val){
        if(numsSize==0) return numsSize;//判断为空情况
        int *left=nums;//使用左右双指针
        int *right=nums+numsSize-1;
        while(left<right){
            while(*left!=val&&left<right) left++;//左指针移到等于val的地方
            while(*right==val&&left<right) right--;//右指针移到不等于val的地方
            *left=*right;//右指针值覆盖左指针
            right--;//右指针左移
        } 
        return left-nums+(*left!=val);//返回长度
    }
  • 相关阅读:
    php 7.1 openssl_decrypt() 代替 mcrypt_module_open() 方法
    关于Http_build_query的用法
    git fetch 和git pull 的差别
    PhpStorm 头部注释、类注释和函数注释的设置
    输出信息log4j.properties的作用与使用方法
    字段设置ALV中下拉列表列的实现
    遍历中序C语言实现二叉树的递归遍历与非递归遍历
    搜索中文Solr Analysis And Solr Query Solr分析以及查询
    记忆指向指针常量 常量指针 常量指针常量
    匹配位置KMP算法深入浅出
  • 原文地址:https://www.cnblogs.com/ming-4/p/11918733.html
Copyright © 2020-2023  润新知