- 反转链表【链表】
- 排序【排序】
- 合并有序数组【归并】【双指针】
- 汽水瓶【递归】
- 明明的随机数
- 跳台阶【动态规划】【递归】【数学】
- LRU实现【】
- NC105 二分查找-II【查找】
- NC7 买卖股票的最好时机
- 26. 删除有序数组中的重复项【双指针】">26. 删除有序数组中的重复项【双指针】
- NC88 寻找第K大【排序】
- NC19 子数组的最大累加和问题【动态规划】
- HJ1 字符串最后一个单词的长度【 数组】【字符串】
- 统计字符出现的次数【字符串】
- 大数加法【字符串】
- HJ4 字符串分隔【字符串】
- HJ6 质数因子【数学】
- 字符集合【字符串】
- 删字符
- HJ31 单词倒排
- HJ39 判断两个IP是否属于同一子网
- 判断链表中是否有环【链表】【双指针】
反转链表【链表】
描述
输入一个链表,反转链表后,输出新链表的表头。
示例
输入:{1,2,3}返回值:{3,2,1}
自测
/*** struct ListNode {* int val;* struct ListNode *next;* };*//**** @param pHead ListNode类* @return ListNode类*/struct ListNode* ReverseList(struct ListNode* pHead ) {// write code here//输入检查if(pHead == NULL)return NULL;struct ListNode* p_index = NULL;struct ListNode* p_next_orig = NULL;struct ListNode* p_pre_orig = NULL;//获取P1,需要注意的是本到题目的pHead就是指向第一个元素p_index = pHead;//检查Pwhile(p_index->next != NULL){//保留原始的下一个元素p_next_orig = p_index->next;//重新赋值当前元素的下一个元素p_index->next = p_pre_orig;//将前元素作为下一个元素的元前一个元素p_pre_orig = p_index;//进入原始下一个元素p_index = p_next_orig;}//将最后一个元素的下一个元素改为原始的上一个元素p_index->next = p_pre_orig;//将最后一个元素赋值给头指针的nextpHead = p_index;return pHead;}
排序【排序】
描述
给定一个数组,请你编写一个函数,返回该数组排序后的形式。
示例1
输入:[5,2,3,1,4]复制返回值:复制[1,2,3,4,5]
示例2
输入:
[5,1,6,2,5]
复制
返回值:复制
[1,2,5,5,6]
备注
数组的长度不大于100000,数组中每个数的绝对值不超过10^9109
自测(选择排序)
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 将给定数组排序
* @param arr int整型一维数组 待排序的数组
* @param arrLen int arr数组长度
* @return int整型一维数组
* @return int* returnSize 返回数组行数
*/
int* MySort(int* arr, int arrLen, int* returnSize ) {
// write code here
//输入检查
if(arr == NULL)
return arr;
*returnSize = arrLen;
//选择排序(超时)
int i = 0;
int j = 0;
int max_temp = 0;
int max_index = 0;
for(i = 0; i < arrLen -1; i++)
{
//初始化最大值
max_temp = arr[0];
max_index = 0;
for( j = 1; j < arrLen - i; j++)
{
//查找最大值
if( max_temp < arr[j])
{
max_temp = arr[j];
max_index = j;
}
}
//将最大值放到最后
arr[max_index] = arr[ arrLen - i-1];
arr[ arrLen - i-1] = max_temp;
}
return arr;
}
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 将给定数组排序
* @param arr int整型一维数组 待排序的数组
* @param arrLen int arr数组长度
* @return int整型一维数组
* @return int* returnSize 返回数组行数
*/
int cmpfun(const void *a, const void *b)
{
return *((int *)a) - *((int *)b);
}
int* MySort(int* arr, int arrLen, int* returnSize ) {
// write code here
//输入检查
if(arr == NULL)
return arr;
*returnSize = arrLen;
//使用快排
qsort(arr, arrLen, sizeof(int),cmpfun);
return arr;
}
合并有序数组【归并】【双指针】
描述
给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。
示例 1
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
示例 2
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
提示
nums1.length == m + n
nums2.length == n
0 <= m, n <= 200
1 <= m + n <= 200
-109 <= nums1[i], nums2[i] <= 109
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
自测
#直接合并使用快排
int cmp(const void * a, const void * b)
{
return *(int *)a - *(int *)b;
}
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
memcpy((void *)(nums1 + m) ,(void *) nums2, n * 4);
qsort(nums1, m+n, sizeof(int), cmp);
}
#使用逆向双指针(先在num1中排最大值)
根据字符出现频率排序
给定一个字符串,请将字符串里的字符按照出现的频率降序排列。
示例 1
输入:
“tree”
输出:
“eert”
解释:
‘e’出现两次,’r’和’t’都只出现一次。
因此’e’必须出现在’r’和’t’之前。此外,”eetr”也是一个有效的答案。
示例 2
输入:
“cccaaa”
输出:
“cccaaa”
解释:
‘c’和’a’都出现三次。此外,”aaaccc”也是有效的答案。
注意”cacaca”是不正确的,因为相同的字母必须放在一起。
示例 3
输入:
“Aabb”
输出:
“bbAa”
解释:
此外,”bbaA”也是一个有效的答案,但”Aabb”是不正确的。
注意’A’和’a’被认为是两种不同的字符。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-characters-by-frequency
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
自测
char * frequencySort(char * s){
if(s == NULL)
return s;
int acs_table[256] = {0};
int s_lens = strlen(s);
//统计字符个数
for (int i = 0; i < s_lens; i++)
{
acs_table[s[i]]++;
}
long sorted_index = 0;
for (int j = 0; j < 256; j++ )
{
int max_index = 0;
long max_frequence = 0;
//找到最大频率
for(int i = 0; i < 256; i++)
{
//记录频率最大的字符
if(acs_table[i] > max_frequence)
{
max_index = i;
max_frequence = acs_table[i];
}
}
if(max_frequence ==0)
continue;
//排列最大的字符
for(int i = 0; i < max_frequence; i++)
s[sorted_index++] = max_index;
//清空最大的字符
acs_table[max_index] = 0;
//
if(sorted_index >= s_lens)
break;
}
return s;
}

汽水瓶【递归】
描述
有这样一道智力题:“某商店规定:三个空汽水瓶可以换一瓶汽水。小张手上有十个空汽水瓶,她最多可以换多少瓶汽水喝?”答案是5瓶,方法如下:先用9个空瓶子换3瓶汽水,喝掉3瓶满的,喝完以后4个空瓶子,用3个再换一瓶,喝掉这瓶满的,这时候剩2个空瓶子。然后你让老板先借给你一瓶汽水,喝掉这瓶满的,喝完以后用3个空瓶子换一瓶满的还给老板。如果小张手上有n个空汽水瓶,最多可以换多少瓶汽水喝?
来源:牛客网
链接:https://www.nowcoder.com/questionTerminal/fe298c55694f4ed39e256170ff2c205f?answerType=1&f=discussion
输入描述:
输入文件最多包含10组测试数据,每个数据占一行,仅包含一个正整数n(1<=n<=100),表示小张手上的空汽水瓶数。n=0表示输入结束,你的程序不应当处理这一行。
输出描述:
对于每组测试数据,输出一行,表示最多可以喝的汽水瓶数。如果一瓶也喝不到,输出0。
示例
输入
3 10 81 0
输出
1 5 40
自测
#include <stdio.h>
#include <string.h>
//递归解决问题
int solving( int n)
{
if(n <=1)
return 0;
if(n == 2)
return 1;
int this_water = n/3;
int next_bottle = n/3 + n%3;
if( next_bottle == 1 )
return this_water;
else
{
int next_water = solving( next_bottle);
return (next_water + this_water);
}
}
int main()
{
int input_array[10] = {0};
int resolv_array[10] = {0};
int input_num = 0;
int input_temp = 0;
//保存用户输入数据
while(scanf("%d", &input_temp) == 1)
{
if(input_temp == 0 || input_temp > 100)
{
break;
}
input_array[input_num] = input_temp;
input_num++;
if(input_num >= 10)
break;
}
// 解决数组
for(int i=0; i < input_num; i++ )
{
resolv_array[i] = solving( input_array[i]);
printf("%d\n", resolv_array[i] );
}
return 0;
}
明明的随机数
描述
明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤1000),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作(同一个测试用例里可能会有多组数据(用于不同的调查),希望大家能正确处理)。
注:测试用例保证输入参数的正确性,答题者无需验证。测试用例不止一组。
当没有新的输入时,说明输入结束。
输入描述
注意:输入可能有多组数据(用于不同的调查)。每组数据都包括多行,第一行先输入随机整数的个数N,接下来的N行再输入相应个数的整数。具体格式请看下面的”示例”。
输出描述
返回多行,处理后的结果
实例
输入例子1:
3
2
2
1
11
10
20
40
32
67
40
20
89
300
400
15
输出例子1:
1
2
10
15
20
32
40
67
89
300
400
例子说明1:
输入解释:
第一个数字是3,也即这个小样例的N=3,说明用计算机生成了3个1到1000之间的随机整数,接下来每行一个随机数字,共3行,也即这3个随机数字为:
2
1
1
所以第一个小样例的输出为:
1
2
第二个小样例的第一个数字为11,也即...(类似上面的解释)...
所以第二个小样例的输出为:
10
15
20
32
40
67
89
300
400
所以示例1包含了两个小样例!!
自测
/*
* main.c
*
* Created on: Aug 27, 2021
* Author: mate
*/
#include <stdio.h>
#include <string.h>
int main()
{
int input_array[1000] = {0};
int input_num = 0;
int input_temp = 0;
int nums = 0;
while( scanf("%d", &nums) == 1 )
{
//保存用户输入数据
input_num = 0;
memset(input_array, 0, sizeof(input_array));
while(scanf("%d", &input_temp) == 1)
{
input_array[input_temp - 1] = 1;
input_num ++;
if(input_num == nums)
break;
}
//输出
for(int i=0; i < 1000 && input_num > 0; i++ )
{
if(input_array[i] == 1)
{
printf("%d\n",i+1);
input_num --;
}
}
}
return 0;
}
跳台阶【动态规划】【递归】【数学】
描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
示例1
输入:
2
返回值:
2
示例2
输入:
7
返回值:
21
方法一:递归
题目分析,假设f[i]表示在第i个台阶上可能的方法数。逆向思维。如果我从第n个台阶进行下台阶,下一步有2中可能,一种走到第n-1个台阶,一种是走到第n-2个台阶。所以f[n] = f[n-1] + f[n-2].
那么初始条件了,f[0] = f[1] = 1。
所以就变成了:f[n] = f[n-1] + f[n-2], 初始值f[0]=1, f[1]=1,目标求f[n]
int Fibonacci(int n) {
if (n<=1) return 1;
return Fibonacci(n-1) + Fibonacci(n-2);
}
方法二:动态规划
那就用动态规划,优化掉递归栈空间。
方法二是从上往下递归的然后再从下往上回溯的,最后回溯的时候来合并子树从而求得答案。
那么动态规划不同的是,不用递归的过程,直接从子树求得答案。过程是从下往上。
int jumpFloor(int number ) {
// write code here
int last_jump_way = 1;
int pre_last_jump_way = 0;
int jump_way = 0;
int step;
for(step = 1; step <= number; step++)
{
jump_way = last_jump_way + pre_last_jump_way;
//更新前两组
pre_last_jump_way = last_jump_way;
last_jump_way = jump_way;
}
return jump_way;
}
LRU实现【】
描述
设计LRU(最近最少使用)缓存结构,该结构在构造时确定大小,假设大小为K,并有如下两个功能
1. set(key, value):将记录(key, value)插入该结构
2. get(key):返回key对应的value值
提示:
1.某个key的set或get操作一旦发生,认为这个key的记录成了最常使用的,然后都会刷新缓存。
2.当缓存的大小超过K时,移除最不经常使用的记录。
3.输入一个二维数组与K,二维数组每一维有2个或者3个数字,第1个数字为opt,第2,3个数字为key,value
若opt=1,接下来两个整数key, value,表示set(key, value)
若opt=2,接下来一个整数key,表示get(key),若key未出现过或已被移除,则返回-1
对于每个opt=2,输出一个答案
4.为了方便区分缓存里key与value,下面说明的缓存里key用””号包裹
进阶:你是否可以在O(1)的时间复杂度完成set和get操作
示例1
输入:
[[1,1,1],[1,2,2],[1,3,2],[2,1],[1,4,4],[2,2]],3
复制
返回值:复制
[1,-1]
说明:
[1,1,1],第一个1表示opt=1,要set(1,1),即将(1,1)插入缓存,缓存是{"1"=1}
[1,2,2],第一个1表示opt=1,要set(2,2),即将(2,2)插入缓存,缓存是{"1"=1,"2"=2}
[1,3,2],第一个1表示opt=1,要set(3,2),即将(3,2)插入缓存,缓存是{"1"=1,"2"=2,"3"=2} [2,1],第一个2表示opt=2,要get(1),返回是[1],因为get(1)操作,缓存更新,缓存是{"2"=2,"3"=2,"1"=1}
[1,4,4],第一个1表示opt=1,要set(4,4),即将(4,4)插入缓存,但是缓存已经达到最大容量3,移除最不经常使用的{"2"=2},插入{"4"=4},缓存是{"3"=2,"1"=1,"4"=4}
[2,2],第一个2表示opt=2,要get(2),查找不到,返回是[1,-1]
示例2
输入:
[[1,1,1],[1,2,2],[2,1],[1,3,3],[2,2],[1,4,4],[2,1],[2,3],[2,4]],2
复制
返回值:复制
[1,-1,-1,3,4]
备注:
1 \leq K \leq N \leq 10^51≤K≤N≤105
-2 \times 10^9 \leq x,y \leq 2 \times 10^9−2×109≤x,y≤2×109
数组换成map最好
/**
* lru design
* @param operators int整型二维数组 the ops
* @param operatorsRowLen int operators数组行数
* @param operatorsColLen int* operators数组列数
* @param k int整型 the k
* @return int整型一维数组
* @return int* returnSize 返回数组行数
*/
struct lru_elemnt {
int value;
int lru_counter;
char get_index;
};
//设置未使用计数
void set_lru_counter (struct lru_elemnt * lru_elemnts)
{
for(int i = 0; i< 100000; i++)
{
if(lru_elemnts[i].value != -1)
lru_elemnts[i].lru_counter ++;
}
}
//检查最久未使用
void check_lru (struct lru_elemnt * lru_elemnts, int max_k)
{
for(int i = 0; i< 100000; i++)
{
if(lru_elemnts[i].lru_counter <= max_k || lru_elemnts[i].lru_counter == 2*max_k)
continue;
lru_elemnts[i].value = -1;
lru_elemnts[i].lru_counter = 2*max_k;
break;
}
}
int* LRU(int** operators, int operatorsRowLen, int* operatorsColLen, int k, int* returnSize ) {
static int k_counter = 0;
static int get_counter = 0;
static struct lru_elemnt lru_elemnts[500000];
static int get_elemnts[500000];
// write code here
//初始化
for(int i = 0; i< 100000; i++)
{
lru_elemnts[i].value = -1;
lru_elemnts[i].lru_counter = 2*k;
lru_elemnts[i].get_index = 0;
}
for(int i = 0; i < operatorsRowLen; i++)
{
//set
if(operatorsColLen[i] == 3 && operators[i][0] ==1 )
lru_elemnts[operators[i][1]].value = operators[i][2];
//get
if(operatorsColLen[i] == 2 && operators[i][0] ==2)
{
get_elemnts[get_counter] = lru_elemnts[operators[i][1]].value;
get_counter++;
}
//设置计数
if(lru_elemnts[operators[i][1]].value != -1)
{
lru_elemnts[operators[i][1]].lru_counter = 0;
set_lru_counter(lru_elemnts);
}
//检查最久未使
check_lru (lru_elemnts, k);
}
//输出GET
*returnSize = get_counter;
return get_elemnts;
}
NC105 二分查找-II【查找】
描述
请实现有重复数字的升序数组的二分查找
给定一个 元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的第一个出现的target,如果目标值存在返回下标,否则返回 -1
示例1
输入:
[1,2,4,4,5],4
复制
返回值:复制
2
说明:
从左到右,查找到第1个为4的,下标为2,返回2
示例2
输入:
[1,2,4,4,5],3
复制
返回值:复制
-1
示例3
输入:
[1,1,1,1,1],1
复制
返回值:
�
0
自测
确保只剩下两个元素
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 如果目标值存在返回下标,否则返回 -1
* @param nums int整型一维数组
* @param numsLen int nums数组长度
* @param target int整型
* @return int整型
*/
int search(int* nums, int numsLen, int target ) {
// write code here
if(numsLen ==0 || target < nums[0] || target > nums[numsLen-1])
return -1;
if(target == nums[0] )
return 0;
int first_index = 0;
int end_index = numsLen-1;
int mid_index = (first_index + end_index)/2;
while(numsLen != 1)
{
mid_index = (first_index + end_index)/2;
if(nums[mid_index] >= target )
end_index = mid_index;
else
first_index = mid_index +1;
numsLen = end_index - first_index +1;
}
if(nums[first_index] == target)
return first_index;
else
return end_index;
}
NC7 买卖股票的最好时机
描述
假设你有一个数组,其中第\ i i 个元素是股票在第\ i i 天的价格。
你有一次买入和卖出的机会。(只有买入了股票以后才能卖出)。请你设计一个算法来计算可以获得的最大收益。
示例1
输入:
[1,4,2]
复制
返回值:复制
3
示例2
输入:
[2,4,1]
复制
返回值:
�
自测
int maxProfit(int *prices,int pricesSize){
if(prices == NULL || pricesSize == 0)
return 0;
int min = prices[0];
int maxprofit = -1;
for(int i = 0;i < pricesSize; ++i){
//min用来维护历史的最小值
if(min > prices[i])
min = prices[i];
//max用来管理最大的利润
if(maxprofit < prices[i] - min)
maxprofit = prices[i] - min;
}
return max;
}
26. 删除有序数组中的重复项【双指针】
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
说明
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);
// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
示例 1
输入:nums = [1,1,2]
输出:2, nums = [1,2]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
示例 2
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
提示
0 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums 已按升序排列
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
自测
int removeDuplicates(int* nums, int numsSize){
if(numsSize == 0)
return 0;
int fast_index = 1;
int slow_index = 0;
for( ; fast_index < numsSize; fast_index++ )
{
if(nums[fast_index] != nums[slow_index])
{
slow_index++;
nums[slow_index] = nums[fast_index];
}
}
return ++slow_index;
}
NC88 寻找第K大【排序】
描述
有一个整数数组,请你根据快速排序的思路,找出数组中第 大的数。
给定一个整数数组 ,同时给定它的大小n和要找的
,请返回第
大的数(包括重复的元素,不用去重),保证答案存在。
要求时间复杂度
示例1
输入:
[1,3,5,2,2],5,3
复制
返回值:复制
2
示例2
输入:
[10,10,9,9,8,7,5,6,4,3,4,2],12,3
复制
返回值:复制
9
说明:
去重后的第3大是8,但本题要求包含重复的元素,不用去重,所以输出9
自测
/**
*
* @param a int整型一维数组
* @param aLen int a数组长度
* @param n int整型
* @param K int整型
* @return int整型
*/
int cmp(const void *a, const void *b)
{
return (*(int *)b - *(int *)a);
}
int findKth(int* a, int aLen, int n, int K ) {
// write code here
if(n <=0 || K < 1)
return 0;
//排序
qsort(a, aLen, sizeof(int),cmp);
//取下标
return a[K-1];
}
NC19 子数组的最大累加和问题【动态规划】
描述
给定一个数组arr,返回子数组的最大累加和
例如,arr = [1, -2, 3, 5, -2, 6, -1],所有子数组中,[3, 5, -2, 6]可以累加出最大的和12,所以返回12.
题目保证没有全为负数的数据
[要求]
时间复杂度为O(n)O(n),空间复杂度为O(1)O(1)
示例1
输入:
[1, -2, 3, 5, -2, 6, -1]
复制
返回值:复制
12
备注
1 \leq N \leq 10^51≤N≤105
|arr_i| \leq 100∣arri∣≤100
自测
/**
* max sum of the subarray
* @param arr int整型一维数组 the array
* @param arrLen int arr数组长度
* @return int整型
*/
//动态规划
int maxsumofSubarray(int* arr, int arrLen ) {
// write code here
int max_sum = 0;
int sum = 0;
for(int i = 0; i < arrLen; i++)
{
sum += arr[i];
if(sum < 0)
sum = 0; //抛弃小的值
if(sum > max_sum)
max_sum = sum;
}
return max_sum;
}
HJ1 字符串最后一个单词的长度【 数组】【字符串】
描述
计算字符串最后一个单词的长度,单词以空格隔开,字符串长度小于5000。
输入描述:
输入一行,代表要计算的字符串,非空,长度小于5000。
输出描述:
输出一个整数,表示输入字符串最后一个单词的长度。
示例1
输入:
hello nowcoder
复制
输出:
8
复制
说明:
最后一个单词为nowcoder,长度为8
自测
#include <stdio.h>
#include <string.h>
int main()
{
char src[5000]= {0};
fgets(src, sizeof(src), stdin);
//输入检查
int src_len = strlen(src);
if(src_len > 5000 )
{
printf("error");
return -1;
}
//查找最后一个空格
int index= 0;
for(int i = src_len; i >= 0; i--){
if(src[i-1] == '\n')
src[i-1] = 0;
if(src[i-1] == ' ')
{
index = i;
break;
}
}
printf("%d", (int)strlen(src + index));
return 0;
}
统计字符出现的次数【字符串】
描述
写出一个程序,接受一个由字母、数字和空格组成的字符串,和一个字母,然后输出输入字符串中该字母的出现次数。不区分大小写,字符串长度小于500。
输入描述:
第一行输入一个由字母和数字以及空格组成的字符串,第二行输入一个字母。
输出描述:
输出输入字符串中含有该字符的个数。
示例1
输入:
ABCabc
A
复制
输出:
2
自测
#include <stdio.h>
#include <string.h>
int main()
{
char temp = 0;
char table[255] = {0};
while((temp =getchar()) != EOF)
{
//小写字母转大写
if( temp >= 'a')
temp -= 'a' - 'A' ;
table[temp] ++;
if(temp == '\n')
{
temp =getchar();
//小写字母转大写s
if( temp >= 'a')
temp -= 'a' - 'A' ;
break;
}
}
printf("%d", table[temp] );
}
大数加法【字符串】
描述
以字符串的形式读入两个数字,编写一个函数计算它们的和,以字符串形式返回。
(字符串长度不大于100000,保证字符串仅由’0’~’9’这10种字符组成)
示例1
输入:
"1","99"
复制
返回值:复制
"100"
说明:
1+99=100
自测
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 计算两个数之和
* @param s string字符串 表示第一个整数
* @param t string字符串 表示第二个整数
* @return string字符串
*/
/*
num = 0~9
*/
char num2char (int num )
{
return (('0' - 0) + num );
}
int char2num(char a)
{
return (a- ('0' - 0));
}
char* solve(char* s, char* t ) {
// write code here
int sLen = strlen(s);
int tLen = strlen(t);
int maxLen = 0;
if(sLen >= tLen)
maxLen = sLen+5;
else
maxLen = tLen+5;
char *result = (char *)malloc(maxLen);
memset(result, 0, maxLen);
int i=0;
int is_full = 0;
int a,b,x,y;
while(sLen >0 || tLen > 0 || is_full)
{
x = 0;
y = 0;
if(sLen >0)
{
a = s[sLen -1];
x = char2num(a);
sLen--;
}
if(tLen > 0)
{
b= t[tLen-1];
y= char2num(b);
tLen--;
}
result[i]= num2char( (x + y + is_full) % 10 );
is_full =(x + y + is_full) / 10;
i++;
}
maxLen = strlen(result);
for(int i = 0; i < maxLen/2; i++)
{
a = result[i];
result[i] = result[maxLen -1-i];
result[maxLen -1-i] =a;
}
return result;
}
HJ4 字符串分隔【字符串】
描述
•连续输入字符串,请按长度为8拆分每个字符串后输出到新的字符串数组;
•长度不是8整数倍的字符串请在后面补数字0,空字符串不处理。
输入描述:
连续输入字符串(输入多次,每个字符串长度小于100)
输出描述:
输出到长度为8的新字符串数组
示例1
输入:
abc
123456789
输出:
abc00000
12345678
90000000
自测
#include<stdio.h>
#include<string.h>
int main()
{
char s_temp[9] = {0};
memset(s_temp, '0', 8);
char s_index =0;
char c_temp = 0;
while( (c_temp = getchar()) != EOF)
{
if(c_temp == '\n' )
{
if( s_index > 0)
{
printf("%s\n", s_temp);
s_index = 0;
memset(s_temp, '0', 8);
}
continue;
}
s_temp[s_index] = c_temp;
s_index ++;
if(s_index == 8 )
{
printf("%s\n", s_temp);
s_index = 0;
memset(s_temp, '0', 8);
continue;
}
}
return 0;
}
HJ6 质数因子【数学】
描述
功能:输入一个正整数,按照从小到大的顺序输出它的所有质因子(重复的也要列举)(如180的质因子为2 2 3 3 5 )
最后一个数后面也要有空格
输入描述:
输入一个long型整数
输出描述:
按照从小到大的顺序输出它的所有质数的因子,以空格隔开。最后一个数后面也要有空格。
示例1
输入:
180
复制
输出:
2 2 3 3 5
自测
#include<stdio.h>
int main()
{
long in = 0;
scanf("%ld",&in);
long ope = in;
int i = 2;
while( i <= ope && i*i <= in )
{
//一个因子多次计算
while(ope % i == 0)
{
printf("%d ",i);
ope /=i ;
}
i++;
}
//如果遍历完了i~sqrt(in),ope还未变成1,则说明有一个较大的质因子,即为剩余in本身,存储即可
if(ope > 1)
printf("%d ", ope);
}
字符集合【字符串】
输入描述
每组数据输入一个字符串,字符串最大长度为100,且只包含字母,不可能为空串,区分大小写。
输出描述
每组数据一行,按字符串原有的字符顺序,输出字符集合,即重复出现并靠后的字母不输出。
输入例子1:
abcqweracb
输出例子1:
abcqwer
自测
/*
============================================================================
Name : displayArr.c
Author :
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
#include <stdio.h>
#include <string.h>
int is_record(char temp, char * arr, int arrLen, int recodNum)
{
if(recodNum > arrLen)
return -1;
for(int i = 0; i< recodNum; i++)
{
if(arr[i] == temp)
return 1;
}
return 0;
}
int main() {
char arr[110] = {0};
char temp = 0;
int record = 0;
while( (temp = getchar()) != EOF)
{
if(temp == '\n')
{
printf("%s\n",arr);
record =0;
memset(arr, 0, 110);
continue;
}
//若是未记录,则进行记录
if(is_record(temp, arr, 110, record) == 0)
{
arr[record] = temp;
record ++;
}
}
return 0;
}
删字符
有一个数组a[N]顺序存放0~N-1,要求每隔两个数删掉一个数,到末尾时循环至开头继续进行,求最后一个被删掉的数的原始下标位置。以8个数(N=7)为例:{0,1,2,3,4,5,6,7},0->1->2(删除)->3->4->5(删除)->6->7->0(删除),如此循环直到最后一个数被删除。
输入描述
每组数据为一行一个整数n(小于等于1000),为数组成员数,如果大于1000,则对a[999]进行计算。
输出描述
一行输出最后一个被删掉的数的原始下标位置。
输入例子1:
8
输出例子1:
6
自测
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int arrLen =0;
while( scanf("%d", &arrLen)!=EOF)
{
if(arrLen > 1000)
arrLen = 1000;
int * arr = ( int *)malloc(arrLen * sizeof(int));
memset(arr, 0, sizeof(int) * arrLen);
int rmin = arrLen;
char dele_index = 0;
int fron_index = 0;
int last_delet_index = 0;
while( rmin > 0)
{ //寻找删除位置
if(arr[fron_index] != -1)
dele_index ++;
//执行删除
if(dele_index == 3)
{
while( arr[fron_index] == -1)
fron_index++;
//删除
arr[fron_index] = -1;
dele_index =0;
rmin--;
last_delet_index = fron_index;
}
fron_index ++;
if(fron_index == arrLen)
fron_index = 0;
}
printf("%d\n", last_delet_index);
free(arr);
}
return 0;
}
HJ31 单词倒排
描述
对字符串中的所有单词进行倒排。
说明:
1、构成单词的字符只有26个大写或小写英文字母;
2、非构成单词的字符均视为单词间隔符;
3、要求倒排后的单词间隔符以一个空格表示;如果原字符串中相邻单词间有多个间隔符时,倒排转换后也只允许出现一个空格间隔符;
4、每个单词最长20个字母;
输入描述:
输入一行以空格来分隔的句子
输出描述:
输出句子的逆序
示例1
输入:
I am a student
复制
输出:
student a am I
复制
示例2
输入:
$bo*y gi!r#l
复制
输出:
l r gi y bo
自测
#include <stdio.h>
int main()
{
char temp = 0;
char oneSpace = 0;
char str[255][22] ;
memset(str, 0, sizeof(str));
char changeLine = 0;
char partNum = 0;
char charNum = 0;
while( (temp = getchar()) != EOF)
{
if( (temp >= 'a' && temp <= 'z') || (temp >= 'A' && temp <= 'Z'))
{
str[partNum][charNum] = temp;
charNum ++;
oneSpace = 0;
}
else if( oneSpace == 0)
{
partNum++;
charNum =0;
oneSpace = 1;
}
}
for(int i = partNum - 1; i >= 0; i--)
printf("%s ", str[i]);
return 0;
}
HJ39 判断两个IP是否属于同一子网
描述
子网掩码是用来判断任意两台计算机的IP地址是否属于同一子网络的根据。
子网掩码与IP地址结构相同,是32位二进制数,其中网络号部分全为“1”和主机号部分全为“0”。利用子网掩码可以判断两台主机是否中同一子网中。若两台主机的IP地址分别与它们的子网掩码相“与”后的结果相同,则说明这两台主机在同一子网中。
示例:
I P 地址 192.168.0.1
子网掩码 255.255.255.0
转化为二进制进行运算:
I P 地址 11000000.10101000.00000000.00000001
子网掩码 11111111.11111111.11111111.00000000
AND运算 11000000.10101000.00000000.00000000
转化为十进制后为:
192.168.0.0
I P 地址 192.168.0.254
子网掩码 255.255.255.0
转化为二进制进行运算:
I P 地址 11000000.10101000.00000000.11111110
子网掩码 11111111.11111111.11111111.00000000
AND运算 11000000.10101000.00000000.00000000
转化为十进制后为:
192.168.0.0
通过以上对两台计算机IP地址与子网掩码的AND运算后,我们可以看到它运算结果是一样的。均为192.168.0.0,所以这二台计算机可视为是同一子网络。
输入一个子网掩码以及两个ip地址,判断这两个ip地址是否是一个子网络。
若IP地址或子网掩码格式非法则输出1,若IP1与IP2属于同一子网络输出0,若IP1与IP2不属于同一子网络输出2。
注:
有效掩码与IP的性质为:
1. 掩码与IP每一段在 0 - 255 之间
2. 掩码的二进制字符串前缀为网络号,都由‘1’组成;后缀为主机号,都由’0’组成
输入描述:
多组输入,一组3行,第1行是输入子网掩码、第2,3行是输入两个ip地址
输出描述:
若IP地址或子网掩码格式非法则输出1,若IP1与IP2属于同一子网络输出0,若IP1与IP2不属于同一子网络输出2
示例1
输入:
255.255.255.0
192.168.224.256
192.168.10.4
255.0.0.0
193.194.202.15
232.43.7.59
255.255.255.0
192.168.0.254
192.168.0.1
输出:
1
2
0
说明:
对于第一个例子:
255.255.255.0
192.168.224.256
192.168.10.4
其中IP:192.168.224.256不合法,输出1
对于第二个例子:
255.0.0.0
193.194.202.15
232.43.7.59
2个与运算之后,不在同一个子网,输出2
对于第三个例子,2个与运算之后,如题目描述所示,在同一个子网,输出0
自测
#include <stdio.h>
#include <string.h>
#define MASK 1
#define IP 0
unsigned int arr2int (unsigned char *arr, int arrLen)
{
unsigned long temp = 0 ;
for(int i = 0; i < arrLen; i++)
{
temp <<=8;
temp |= arr[i];
}
return temp;
}
//合法性检查
int is_legal( char *ip, int is_mask)
{
unsigned char buf[4] = {0};
int j = 0;
unsigned char arry_temp[32] = {0};
strcpy(arry_temp, ip);
char *strtemp = NULL;
strtemp = strtok(arry_temp, ".");
while(strtemp !=NULL)
{
if( atoi(strtemp) > 255 || atoi(strtemp) <0)
return 1;
buf[j] = atoi(strtemp);
j++;
strtemp = strtok(NULL, ".");
}
if(is_mask == MASK)
{
unsigned int max_mask = 0xffffffff;
while(( max_mask <<= 1) > 0 )
{
if(arr2int (buf, 4) == max_mask)
return 0;
}
return 1;
}
return 0;
}
//转为unsigned char
unsigned char * str2arr(char *str, unsigned char * result)
{
char temp[8] = {0};
char temp_index = 0;
int i = 0;
int j =0;
for( ; i< strlen(str); i++)
{
if(str[i] >= '0' && str[i] <= '9')
{
temp[temp_index] = str[i];
temp_index ++;
}
else
{
result[j] = atoi(temp);
j++;
temp_index =0;
memset(temp, 0, 8);
}
}
return result;
}
//判断是否是统一网段
int is_samenet(char *mask, char *ip1, char *ip2)
{
//合法性检查
if( is_legal( mask, MASK) || is_legal( ip1, IP)|| is_legal( ip2, IP))
return 1;
//转为unsigned char
unsigned char mask_int[4] = {0};
unsigned char ip1_int[4] = {0};
unsigned char ip2_int[4] = {0};
str2arr(mask, mask_int);
str2arr(ip1, ip1_int);
str2arr(ip2, ip2_int);
//比较
for(int i = 0; i < 4; i++)
{
if( (mask_int[i] & ip1_int[i]) != (mask_int[i] & ip2_int[i]))
return 2;
}
return 0;
}
int main()
{
unsigned char mask[32] = {0};
unsigned char ip_1[32] = {0};
unsigned ip_2[32] = {0};
//获取掩码
while(scanf("%s", mask) != EOF)
{
scanf("%s", ip_1);
scanf("%s", ip_2);
printf("%d\n", is_samenet(mask, ip_1, ip_2));
}
return 0;
}
判断链表中是否有环【链表】【双指针】
如果有环则返回true,否则返回false。
数据范围:链表长度 ,链表中任意节点的值满足
要求:空间复杂度 ,时间复杂度
输入分为2部分,第一部分为链表,第二部分代表是否有环,然后回组成head头结点传入到函数里面。-1代表无环,其他的数字代表有环,这些参数解释仅仅是为了方便读者自测调试。实际在编码时读入的是链表的头节点。
示例1
输入:
{3,2,0,-4},1
复制
返回值:复制
true
说明:
第一部分{3,2,0,-4}代表一个链表,第二部分的1表示,-4到位置1,即-4->2存在一个链接,组成传入的head为一个带环的链表 ,返回true
自测
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
/**
*
* @param head ListNode类
* @return bool布尔型
*/
int hasCycle(struct ListNode* head) {
struct ListNode *slow = head, *fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) return 1;
}
return 0;
}
