[蓝蓝计算机考研算法训练二期]-day20

156 阅读3分钟

28、给定一个n个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target ,如果目标值存在返回下标,否则返回 -1。

示例1:

ext

输入:nums = [-1, 0, 3, 5, 9, 12],target = 9

输出:4

解释:9 出现在 nums 中并且下标为4

示例2:

ext

输入:nums = [-1, 0, 3, 5, 9, 12],target = 2

输出:-1

解释:2 不存在 nums 中因此返回-1

提示:

  • 你可以假设 nums 中所有的元素是不重复的。
  • n 将在[1, 10000]之间
  • nums 的每一个元素都将在[-9999, 9999]之间

思路

先将得到的数据转换为字符串,然后利用二分查找进行搜寻数据。

具体实现

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define MAX_LEN 10000


int main() {
	
	char str[MAX_LEN];
    int num[MAX_LEN];
    int n,i,j=0;
    
    // 将输入的内容按照字符串读入 
	scanf("%s", str);
	// 读取字符串中不含‘[’‘]’的内容 
	for (i = 0; str[i] != ']'; i++) {
        if (str[i] != '[') {
            str[j++] = str[i];
        }
    }
    
    // 读取要删除的数字 
    n = int(str[j+3]-'0');
    str[j] = '\0';  // 确保新字符串以 '\0' 结尾
    
	// 分割字符串并转换为数字
	i=0;
    char *token = strtok(str, ",");
    while (token != NULL) {
        num[i++] = atoi(token);
        token = strtok(NULL, ",");
    }
    
    // i表示第一个位置,j表示最后一个位置 
    int len, mid;
    len = i;
    i = 0;
	j = len-1;
	// 使用二分法查找 
	while(i < j) {
		mid = (i+j)/2;
		if(num[mid] > n)
			j = mid-1;
		else if(num[mid] < n)
			i = mid+1;
		else {
			printf("%d", mid);
			break;
		}
	}
	if (i >= j) {
		printf("-1");
	}
	
	return 0;
}

image.png

image.png

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

不要使用额外的数组空间,你必须仅使用O(1)额外空间并原地修改输入数组。

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

示例1:

给定 nums = [3, 2, 2, 3],val = 3,函数应该返回新的长度2,并且 nums 中的前两个元素均为2。你不需要考虑数组中超出新长度后面的元素。

示例2:

给定 nums = [0, 1, 2, 2, 3, 0, 4, 2],val = 2,函数应该返回新的长度2,并且 nums 中的前五个元素为0, 1, 3, 0, 4。你不需要考虑数组中超出新长度后面的元素。

思路

这里有一个整体的批处理形式是,[数字,数字,数字,...],数字可以将得到的方括号的内容转变为数组,将最后的数字取出,同时也可以得到数组的长度。这样的话就是对数组进行处理。这里进行处理时用了一个小技巧,i不仅仅代表了原数组的下标,也代表了循环的次数,j才是新数组的新下标,同时在遍历时,在循环内部使用了while判断当前读取的数字是否是给定的值,如果是,count自增,直到不是给定值为止,然后将那个值赋给数组应该的下标num[j]

具体实现

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define MAX_LEN 10000


int main() {
	
	char str[MAX_LEN];
    int num[MAX_LEN];
    int n,i,j=0;
    
    // 将输入的内容按照字符串读入 
	scanf("%s", str);
	// 读取字符串中不含‘[’‘]’的内容 
	for (i = 0; str[i] != ']'; i++) {
        if (str[i] != '[') {
            str[j++] = str[i];
        }
    }
    
    // 读取要删除的数字 
    n = int(str[j+3]-'0');
    str[j] = '\0';  // 确保新字符串以 '\0' 结尾
    
	// 分割字符串并转换为数字
	i=0;
    char *token = strtok(str, ",");
    while (token != NULL) {
        num[i++] = atoi(token);
        token = strtok(NULL, ",");
    }
    
    int len, count=0;
    len = i,j = 0;
	for(i = 0;i < len;i++) {
		while(num[i+count] == n)
			count++;
		num[j] = num[i+count];
		j++;
	}
	for (i=0;i<len-count;i++)
		printf("%d ", num[i]);
	
	printf("\n新数组长度为%d", len-count);
	
	return 0;
}

image.png

image.png

小结

本次算法不算很难,多多思考并结合所学知识,如查找可以适当使用二分查找等。