题目描述
求解思路
这题可以用传统的链表,也可以用数组来写(偷懒写法)
C语言解法
#include<stdio.h>
#include<stdlib.h>
typedef struct LinkList
{
int data;
struct LinkList* next;
}link;
int main() {
//创建头结点并且初始化链表
link* head = (link*)malloc(sizeof(link));
head->next = NULL;
link* cur = head; //cur节点用于追踪最后的结点完成链表插入
int reverseTarget, number, cnt = 0; // 需要查找的倒数第k项、当前输入的数字、链表元素个数
scanf("%d", &reverseTarget);
scanf("%d", &number);
// 对于每一个数 创建节点并插入链表中
link* newNode = (link*)malloc(sizeof(link));
newNode->data = number;
newNode->next = NULL;
cur->next = newNode; //cur在最开始是头结点位置 指向节点newNode实现链表链接
cur = cur->next; //追踪最后的结点
cnt++;
while (number >= 0)
{
scanf("%d", &number);
if (number < 0)
{
break;
}
link* newNode = (link*)malloc(sizeof(link));
newNode->data = number;
newNode->next = NULL;
cur->next = newNode;
cur = cur->next;
cnt++;
}
// 正序在链表中查找倒数第k项
cur = head; // cur节点重新设置为链表的头结点,为了从头开始遍历链表
int target = cnt - reverseTarget + 1; //由于链表我们假定是从1开始的 那么相减后还要+1用实现偏移
/*flag = cnt - target + 1
= 10 - 3 + 1
= 8*/
//1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 ->[8] -> 9 -> 10
int flag = 0; // 标志是否成功遍历了一次链表
while (cur->next && target > 0) {
flag = 1;
cur = cur->next; // 不断向右
target--; //对于每一次cur移动 target-- 有多少个targer就移动多少次
if (target == 0) // target为0 成功找到倒数第k个元素
{
printf("%d", cur->data);
break;
}
}
//如果while循环出来 target不是0(没找到)或flag是0(没遍历),就说明链表长度不足或空链表,输出NULL
if (target != 0 || flag == 0) {
printf("NULL");
}
}
C++解法
C++利用了动态数组vector,简化了很多代码.C语言的解法也可以仿照C++,创建一个数组即可,这里不再写了
#include <bits/stdc++.h>
using namespace std;
vector<int> nums; //滑动窗口思想维持固定k个长度的数组
int main()
{
int k,num;
cin>>k;
while(cin>>num && num>=0) //非负整数持续读入
{
nums.push_back(num);
if(nums.size()>k)
{
nums.erase(nums.begin());
//当数组长度大于k时,删除数组的第一个元素,以维持数组的长度k
}
}
if(nums.size()<k) //如果数据长度小于k 不存在倒数第k个数 输出错误信息
{
cout<<"NULL"<<endl;
}
else
{
cout<<nums[0]<<endl; //此时数组的第一个元素就是倒数第k个数
}
return 0;
}