C_C++编程题:20道算法题

1、在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。时间复杂度 O(row+col)
#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

void Fnid_val(int* arr, int row, int col, int num)
{
	if (NULL != arr && row > 0 && col > 0)
	{
		int tmpRow = 0;
		int tmpCol = col - 1;
		while (tmpRow < row && col >= 0)
		{
			if (arr[tmpRow * col + tmpCol] == num)
			{
				printf("%d,intdex == %d\n", arr[tmpRow * col + tmpCol], tmpRow * col + tmpCol);
				break;
			} 
			else if (arr[tmpRow * col + tmpCol] > num)
			{
				--tmpCol;
			} 
			else
			{
			++tmpRow;
			}
		}
	}
} 

int main()
{
	int arr[4][4] = { 1,2,8,9,
	2,4,9,12,
	4,7,10,13,
	6,8,11,15 };
	Fnid_val((int*)arr, 4, 4, 15);
	return 0;
}

2、要求写一个函数,将字符串中的空格替换为%20。样例: “abc defgx yz”,转换成 “abc%20defgx%20yz”
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void replace(char* arr, char* arr2)
{
    while (*arr != '\0')
    {
        if (*arr != ' ')
        {
            *arr2 = *arr;
            arr2++;
        }
        else
        {
            strcpy(arr2, "%20");
            arr2 += 3;
        }
        arr++;
    }
}

int main()
{
    char arr[20] = "abc defgx yz";
    char arr2[50] = { 0 };
    replace(arr, arr2);
    printf("%s\n", arr2);
    return 0;
}

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

void ReplaceBlank(char* str, int len)
{
	int MLen = 0;//计算字符的个数
	int NumBlank = 0;//计算空格的数组
	int IndexofMLen = 0;
	int Indexofnew = 0;
	int newlen = 0;
	int i = 0;//从0号下标开始遍历
	if (str == NULL || len <= 0)
	{
		return;
	} 
	while(str[i] != '\0')
	{
		++MLen;
		if (str[i] == ' ')
		{
			++NumBlank;
		} 
		++i;
	} 
	newlen = MLen + NumBlank * 2;//a%20b%20c%20d a b c d
	if (newlen > len)//newlen是扩充后数组的大小,所以一定要小于len原来大小,不然放不下
	{
		return;
	} 
	IndexofMLen = MLen;
	Indexofnew = newlen;
	while (IndexofMLen >= 0 && Indexofnew > IndexofMLen)
	{
		if (str[IndexofMLen] == ' ')
		{
			str[Indexofnew--] = '0';
			str[Indexofnew--] = '2';
			str[Indexofnew--] = '%';
		} 
		else
		{
			str[Indexofnew--] = str[IndexofMLen];
		} 
		--IndexofMLen;
	}
} 

int main()
{
	char str[30] = "a b c d";
	int len = (sizeof(str) / sizeof(str[0]));
	ReplaceBlank(str, len);
	printf("%s\n", str);
	return 0;
}

3、编写函数,求第n个斐波那契数列的值(非递归)
#include <stdio.h>

int Fib(int n)
{
    int a = 1;
    int b = 1;
    int c = 1;
    while (n > 2)
    {
        c = a + b;
        a = b;
        b = c;
        n--;
    }
    return c;
}

int main()
{
    int n = 0;
    scanf("%d", &n);
    int ret = Fib(n);
    printf("%d\n", ret);
    return 0;
}

4、写一个函数求,求 unsigned int 型变量 x 在内存中二进制 1 的个数
#include <stdio.h>

int CntNumOne(int n)
{
	int count = 0;
    while (n)
    {
        ++count;
        n = (n - 1) & n;
    }
    return count;
}

int main()
{
    printf("%d\n", CntNumOne(-1));

    return 0;
}

5、有一个数组 a , 编写函数,求数组中前K个最小的数字
#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

int FindMin(int a[], int k)
{
    int min = a[0];
    int i = 0;
    for (i = 0; i < k - 1; i++)
    {
        if (a[i] < min)
            min = a[i];
    }
    return min;
}

int main()
{
    int a[] = { 5,3,7,8,1,4,9,10,6,2 };
    int k = 7;

    int ret = FindMin(a, k);

    printf("%d\n", ret);

    return 0;
}

6、在字符串中找出第一个只出现一次的字符。如输入 “abaccdeff” ,则输出 ‘b’ 。
#include <stdio.h>
#include <string.h>

void find_string(char* str)
{
    int len = strlen(str);
    int i = 0;
    for (i = 0; i < len; i++)
    {
        int j = 0;
        int cnt = 1;
        for (j = 0; j < len; j++)
        {
            if (i == j)
                continue;
            if (str[i] == str[j]) {
                cnt = 0;
                break;
            }
        }
        if (cnt == 1) {
            printf("%c\n", str[i]);
            return 0;
        }
    }
}

int main() {
    char arr[] = "abaccdeff";
    find_string(arr);
    return 0;
}
char firstNotRepeate(char* str)
{
	const int size = 256;//表示
	int hashTable[size];
	int i;
	if (str == null) 
	{
		return '\0';
	} 
	for (i = 0; i < size; i++) {
		hashTable[i] = 0;
	} 
	char* pHashKey = str;
	while (*(pHashKey) != '\0')
	{
		hashTable[*(pHashKey++)]++;
	} 
	pHashKey = str;
	while (*(pHashKey) != '\0')
	{
		if (hashTable[*(pHashKey)] == 1)
		{
			return *(pHashKey);
		} 
		pHashKey++;
	} 
	return '\0';
}

7、对于一个字符串,请设计一个高效算法,找到第一次重复出现的字符。测试样例: “qywyer23tdd” , 返回: y
#include <stdio.h>
#include <string.h>

void find_first(char* str)
{
    int len = strlen(str);
    int i = 0;
    for (i = 0; i < len; i++)
    {
        int j = 0;
        for (j = 0; j < len; j++)
        {
            if (i == j)
                continue;
            if (str[i] == str[j])
            {
                printf("%c\n", str[i]);
                return 0;
            }
        }
    }
}

int main()
{
    char arr[] = "qywyer23tddf";
    find_first(arr);
    return 0;
}
#define SIZE 256
char firstNotRepeate(char* str)
{
	char* pHashKey = str;
	int hashTable[SIZE];
	int i;
	for (i = 0; i < SIZE; i++) {
		hashTable[i] = 0;
	} 
	while(*(pHashKey) != '\0')
	{
		hashTable[*(pHashKey++)]++;
	} p
		HashKey = str;
	while (*(pHashKey) != '\0')
	{
		if (hashTable[*(pHashKey)] == 2)
		{
			return *(pHashKey);
		} 
		pHashKey++;
	} 
	return '\0';
} 

int main()
{
	char ch = firstNotRepeate("qywyer23tdd");
	printf("%c\n", ch);
	return 0;
}

8、个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。例如数组为{1,3,5,7,1,3,5,9},找出7和9。
#include <stdio.h>

void find_num(int arr[], int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        int j = 0;
        int cnt = 1;
        for (j = 0; j < sz; j++)
        {
            if (i == j)
                continue;
            if (arr[i] == arr[j])
            {
                cnt = 0;
                break;
            }
        }
        if (cnt == 1)
            printf("%d ", arr[i]);
    }
}

int main()
{
    int arr[] = { 1, 3, 5, 7, 1, 3, 5, 9 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    find_num(arr, sz);
    return 0;
}
void findNumberAppearOnce(int[] arr, int len, int* num1, int* num2)
{
	int resultOR = 0;
	int i = 0;
	int indexOf1 = 0;
	int j = 0;
	if (arr == null || len < 2)
	{
		return null;
	} 
	*num1 = 0;
	*num2 = 0;
	//对数组当中每个数字进行异或,结果为两个不相同的数字异或结果
	for (i = 0; i < len; i++)
	{
		resultOR ^= arr[i];
	} 
	//找出resultOR当中的第一个二进制1是第几位(右 == = 》左)
	indexOf1 = findNumberBits(resultOR);
	//遍历数组,第indexOf1为1的进行异或 不为1的进行异或
	for (j = 0; j < len; j++)
	{
		if (isBit(arr[j], indexOf1))
		{
			*num1 = *num1 ^ arr[j];
		} 
		else
		{
		*num2 = *num2 ^ arr[j];
		}
	}
} 
//从右数的第bit为1
int findNumberBits(int number)
{
	int indexBit = 0;
	while ((number & 1) == 0 && indexBit < 8 * sizeof(int))
	{
		number = number >> 1;
		++indexBit;
	} 
	return indexBit;
} 

bool isBit(int num, int index)
{
	num = num >> index;
	if ((num & 1) == 1)
	{
		return true;
	} 
	return false;
}

9、输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。例如,输入 ”They are students.” 和 ”aeiou” ,则删除之后的第一个字符串变成 ”Thy r stdnts.”
#include <stdio.h>
#include <string.h>

void exchange(char a[], char b[])
{
    int len1 = strlen(a);
    int len2 = strlen(b);
    int i = 0;
    for (i = 0; i < len1; i++)
    {
        int j = 0;
        for (j = 0; j < len2; j++)
        {
            if (a[i] == b[j])
                a[i] = '1';
        }
    }
    for (i = 0; i < len1; i++)
    {
        if (a[i] != '1')
            printf("%c", a[i]);
    }
}

int main()
{
    char a[] = "They are students.";
    char b[] = "aeiou";
    exchange(a, b);
    return 0;
}
#define MAX 256
char* DeleteChars(char* str1, char* str2)
{
	if (str1 == NULL || str2 == NULL)
		return NULL;
	int hashtable[MAX] = { 0 };
	//将str2中字符对应的hashtable数组中的位置上的值设为ture
	while (*str2 != '\0')//"come"
	{
		hashtable[*str2] = 1;
		++str2;
	} 
	char* p = str1;
	char* q = str1;
	while (*p != '\0')
	{
		if (!hashtable[*p])
		{
			*q++ = *p;
		} 
		p++;//因为后面需要找到值 覆盖掉这个为true的值
	} 
	*q = '\0';
	return str1;
} 

int main()
{
	char str1[] = "Welcome biter";
	char str2[] = "come";
	printf("%s\n", DeleteChars(str1, str2));
	return 0;
}

10、编写一个函数,求一个数字是否是回文数。回文数概念:给定一个数,这个数顺读和逆读都是一样的。例如:121,1221是回文数,123,1231不是回文数。
#include <stdio.h>

int is_num(int n)
{
    int n2 = n;
    int y = 0;
    while (n2)
    {
        y = y * 10 + n2 % 10;
        n2 /= 10;
    }
    if (y == n)
        return 1;
    else
        return 0;
}

int main()
{
    int n = 0;
    scanf("%d", &n);
    int ret = is_num(n);
    if (ret == 1)
        printf("YES\n");
    else
        printf("NO\n");

    return 0;
}
void Palindrome(int num)
{
	int newed = 0;
	int n = num;
	while (num > 0)
	{
		newed = newed * 10 + num % 10;
		num /= 10;
	}
	if (n == newed)
	{
		printf("Yes\n");
	}
	else
	{
		printf("No\n");
	}
}

11、模拟实现函数 pow(x,y) , 即实现运算x^y(x的y次方), 这里x和y都为整数。
#include <stdio.h>

long long Pow(int x, int y)
{
    if (y == 0)
        return 1;
    else if (y == 1)
        return x;
    else
    {
        long long i = 0;
        long long x2 = 1;
        for (i = 0; i < y; i++)
        {
            x2 *= x;
        }
        return x2;
    }
}

int main()
{
    long long a = 2;
    long long b = 4;
    long long ret = Pow(a, b);
    printf("%lld", ret);
}
/*函数
pow(x, y)实现运算x ^ y,即x的y次方,这里x和y都为整数。
算法的基本思想是,减少乘法次数,重复利用结算结果,例如:
x ^ 4,如果逐个相乘的话,需要四次乘法。
如果我们这样分解(x ^ 2) * (x ^ 2)就只需要2两次乘法,
因为x ^ 2的结果我们可以重复利用。所以我们最好做对称的分解指数y,
然后求x ^ (y / 2)的平方。
具体算法如下:
1 如果y为偶数,直接计算mypow(x, y / 2) * mypow(x, y / 2);
2 如果y为奇数,则y - 1为偶数,回到了第一种情况。
*/

int Mypow(int x, int y)
{
	int result = 0;
	int tmp = 0;
	if (y == 1) return x;
	tmp = mypow(x, y / 2);
	if (y & 1 != 0) //奇数
	{
		result = x * tmp * tmp;
	}
	else
	{
		result = tmp * tmp;
	} 
	return result;
}

12、如何判断一个数n是否是2的k次方?注意:不用求K是多少,只需要判断,请编写函数实现。
#include <stdio.h>

void is_power(int n)
{
    if ((n & (n - 1)) == 0)
    {
        printf("YES\n");
    }
    else
    {
        printf("NO\n");
    }
}

int main()
{
    int n = 0;
    scanf("%d", &n);

    is_power(n);

    return 0;
}

13、有一张单链表,编写函数求倒数第K个结点
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
	//刚开始的时候,都指向起点,然后p1走k-1步后,p2和p1同时开始走,当p1走到最后一个的时候,p2指向的就是最后一个节点
	ListNode* p1 = pListHead;
	ListNode* p2 = pListHead;
	if (pListHead == NULL || k == 0) {
		return NULL;
	} 
	while(k - 1 > 0)
	{
		if (p1->next != NULL)
		{
			p1 = p1->next;
			--k;
		} 
		else
		{
		cout << "error" << endl;
		return NULL;
		}
	} 
	while(p1->next != NULL)
		{
			p1 = p1->next;
			p2 = p2->next;
		} 
		return p2;
}

14、编写函数,要求逆置单链表(不带头结点)
struct ListNode* reverseList(struct ListNode* head) {
	struct ListNode* rev_head = NULL;
	struct ListNode* prev = NULL;
	struct ListNode* pNode = head;
	while (pNode != NULL)
	{
		struct ListNode* pNext = pNode->next;
		if (pNext == NULL)
		{
			rev_head = pNode;
		} p
			Node->next = prev;
		prev = pNode;
		pNode = pNext;
	} r
		eturn rev_head;
}

15、输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。例如输入的数组为{1,-2,3,10,-4,7,2,-5},和最大的子数组为{3,10,-4,7,2},因此输出为该子数组的和18
int MAX_Arry(int* arr, int sz)
{
	int MAX = arr[0];
	int sum = arr[0];
	int i = 1;
	if (arr == NULL || sz <= 1)
		return 0;
	for (i = 1; i < sz; i++)
	{
		if (sum < 0)
			sum = arr[i];
		else
		{
			sum += arr[i];
		} 
		if(sum > MAX)
			MAX = sum;
	} 
	return MAX;
} 

int main()
{
	int arr[] = { 1,-2,3,10,-4,7,2,-5 };
	int len = sizeof(arr) / sizeof(arr[0]);
	printf("%d\n", MAX_Arry(arr, len));
	return 0;
}

16、如何快速查找到一个单链表的中间位置?编写函数实现
/*设置两个指针,p1, p2, 开始p1, p2均位于链接的头部。
p1 每次步进两步,
p2 每次步进一步
当p1到达链表的末尾时,p2所在的位置就是链表的中间元素
时间复杂度为O(n)
单链表的创造等函数,全部在上课讲过,我们只实现功能函数。
*/

Node * FindMidleNode(pList plist)
{
	Node* pFast = NULL;
	Node* pSlow = NULL;
	assert(plist != NULL);
	pFast = plist->next;
	pSlow = plist->next;
	while (pFast != NULL && pFast->next != NULL)
	{
		pFast = pFast->next->next;
		pSlow = pSlow->next;
	} 
	return pSlow;
}

17、先输入n个整数,按照数据输入的顺序建立一个带头结点的单链表,再输入一个数据m,将单链表中的值为m的结点全部删除。输出删除后的单链表信息。
#include <stdio.h>

//链表结点的定义
struct Node
{
    int date; //数据域
    struct Node* next; //指针域
};

int main()
{
    struct Node* list = NULL; //指向链表的指针
    struct Node* tail = NULL; //指向链表尾部元素的指针
    //输入n
    int n = 0;
    scanf("%d", &n);
    int i = 0;
    int m = 0;
    int d = 0; //要删除的元素
    
    //接收n个数字并尾插到链表中
    for(i=0; i<n; i++)
    {
        scanf("%d", &m);
        struct Node* pn = (struct Node*)malloc(sizeof(struct Node));
        pn->date = m;
        pn->next = NULL;
        
        //插入第一个元素
        if(list == NULL)
        {
            list = pn;
            tail = pn;
        }
        else
        {
            tail->next = pn;
            tail = pn;
        }
    }
        //接收要删除的元素
        scanf("%d", &d);
        
        //删除链表中指定的元素
        struct Node* cur = list;
        struct Node* prev = NULL;
        
        while(cur)
        {
            //找到了要删除的元素
            if(cur->date == d)
            {
                //删除
                //删除的如果是第一个结点
                struct Node* pd = cur;
                if(cur == list)
                {
                    list = list->next;
                    cur = list;
                }
                else
                {
                    prev->next = cur->next;
                    cur = prev->next;
                }
                free(pd);
                n--;
            }
            else
            {
                prev = cur;
                cur = cur->next;
            }
        }
        
        //输出
        printf("%d\n", n);
        cur = list;
        while(cur)
        {
            printf("%d ", cur->date);
            cur = cur->next;
        }
        //释放链表
        cur = list;
        struct Node* del = NULL;
        while(cur)
        {
            del = cur;
            cur = cur->next;
            free(del);
        }
        list = NULL;
    
    return 0;
}


18、求一个有序数组中两个元素值相加为k的数字,返回这两个元素的下标。要求时间复杂度是O(n),空间复杂度O(1)
void SumK(int* arr, int len, int k, int* num1, int* num2)
{
	int low = 0; //从前往后遍历
	int high = len - 1;//从后往前遍历
	int sum;
	while (low <= high)
	{
		sum = arr[low] + arr[high];
		if (sum < k)
		{
			low++;
		} 
		else if (sum > k)
		{
			high--;
		} 
			else
		{
		*num1 = low;
		*num2 = high;
		break;
		}
	}
}

19、字符串压缩. 输入字符串只包含 a-z 字母以及结束标志,请编写函数实现对连续出现的相同字符进行压缩,例如: ”xxxyyyyz” 压缩后字符串为 ”3x4yz” , ”yyyyyyy” 压缩后为 ”7y”
void Compress(char* str)
{
	int count = 1;
	int i = 0;
	assert(str != NULL);
	while (str[i] != '\0')
	{
		if (str[i] == str[i + 1])
		{
			count++;
		} 
		else
		{
		if (count != 1)
		printf("%d",count);
		printf("%c",str[i]);
		count = 1;
		} 
		i++;
	} 
	printf("\n");
}

20、编写代码完成如下功能:删除字符串首尾的空格,中间的连续空格只留一个,原来字符串的顺序不变。如 “as****adadq”(是空格) 变成 “asaadadq”
void Deblank(char* str)
{
	int flag = 0; //代表没开始处理空格
	int p = 0;
	int i = 0;
	while (str[i] != '\0')
	{
		//遇到空格 还没开始处理
		if (!flag && str[i] == ' ')// 遇到空格 让i往后走到不是空格的地方
		{
			i++;
		}
		//遇到不是空格 还没开始处理
		else if (!flag && str[i] != ' ')//不是空格的字符向前赋值
		{
			flag = 1; //开始处理空格
			str[p++] = str[i++];
		}
		//遇到空格 开始处理了
		else if (flag && str[i] == ' ')
		{
			flag = 0; //不处理
			str[p++] = str[i++];
		}
		else
		{
			str[p++] = str[i++];
			flag = 1;
		}
	}
	if (str[p - 1] == ' ') //结尾处多余空格
		str[p - 1] = '\0';
	else
		str[p] = '\0';
}

int main()
{
	char str[] = " as adad q ";
	Deblank(str);
	printf("%s", str);
	return 0;
}
  • 6
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三春去后诸芳尽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值