一道简单的题

阿里巴巴的一道面试题

25.给定一个整数数组和一个整数,返回两个数组的索引,这两个索引指向的数字的加和等于指定的整数。需要最优的算法,分析算法的空间和时间复杂度。

 

#include <iostream>
#include <unordered_map>

using namespace std;
struct STwoIndex
{//数组的两个索引
	int	unFirst;//第一个索引
	int	unSecond;//第二个索引

	STwoIndex()
		:unFirst(-1)
		,unSecond(-1)
	{}//初始化,同时等于0,说明不存在
};

STwoIndex GetArrayIndex(int array[], unsigned int nCount, int nTarget)
{//整数数组,有可能有负数,也可能有重复的数
	STwoIndex twoIndex;
	std::unordered_map<int, int> umValueIndex;
	umValueIndex.reserve(nCount);
	if (nTarget & 0x1)
	{//目标是奇数,重复的暂时不考虑
		for (int i = 0; i < nCount; ++i)
		{
			umValueIndex[array[i]] = i;
		}
	}
	else
	{//目标是偶数,存在2个 nTarget/2的数字的可能性
		int nFirst = -1;
		int nHalf = nTarget >> 1;
		for (int i = 0; i < nCount; ++i)
		{
			if (nHalf == array[i])
			{
				if (nFirst >= 0)
				{//已找到,两个 nTarget/2
					twoIndex.unFirst = nFirst;
					twoIndex.unSecond = i;
					break;
				}
				else
				{
					nFirst = i;
				}
			}
			umValueIndex[array[i]] = i;
		}
	}

	if (twoIndex.unFirst < 0 || twoIndex.unSecond < 0)
	{//遍历一遍,查找结果
		for (auto iter = umValueIndex.begin(); iter != umValueIndex.end(); ++iter)
		{
			if (umValueIndex.find(nTarget - iter->first) != umValueIndex.end())
			{
				auto findIter = umValueIndex.find(nTarget - iter->first);
				if(iter == findIter)
					continue;//找到了自己,不符合
				if (iter->second < findIter->second)
				{
					twoIndex.unFirst = iter->second;
					twoIndex.unSecond = findIter->second;
				}
				else
				{
					twoIndex.unFirst = findIter->second;
					twoIndex.unSecond = iter->second;
				}
				break;
			}
		}
	}

	return twoIndex;
}

int main()
{
	int array[] = {1,1,2,5,-7,-9,0,45,6,3,7,5,5,10,78};
	STwoIndex ti = GetArrayIndex(array, 15, 17); 
}

 

<think>嗯,用户想要一道简单的链表目,我得先回想一下常见的链表问。链表的基础操作包括遍历、插入、删除、反转等等。对于初学者来说,可能反转链表是一个比较经典的目,不过有时候可能稍难。或者删除指定值的节点,可能更简单些? 或者,合并两个有序链表?不过合并的话可能涉及到多个步骤,对于“简单”的要求来说,可能稍微复杂了一点。再想想,像检测链表是否有环可能涉及到快慢指针,可能属于中等难度。那最基础的应该是插入节点或者删除节点。 对了,或许可以一道“删除链表中的指定值节点”。比如给定一个单链表一个整数val,删除所有值为val的节点,返回新的头节点。这样的话,目描述起来简单,实现起来也比较基础,适合新手练习链表的遍历指针操作。 比如示例输入:1 -> 2 -> 6 -> 3 -> 4 -> 5 -> 6,val = 6,那么结果应该是1 -> 2 -> 3 -> 4 -> 5。这例子能清楚说明问。这样的话,用户需要处理头节点可能被删除的情况,以及如何调整指针。 再确认一下目的正确性,这个目确实是常见的,LeetCode上也有类似的目,比如第203“移除链表元素”。所以这个目是合适的。 那接下来需要组织目描述,示例输入输,以及可能的提示。要确保用户能够明确意,并且给的例子足够清晰。同时,可能需要给一些提示,比如使用虚拟头节点来简化操作,或者如何处理连续需要删除的节点。 然后,考虑如何给解答。解答部分需要分步骤说明,比如如何处理头节点,遍历链表时的指针操作,以及边界情况,比如链表为空或者所有节点都需要删除的情况。 另外,要确保使用中文回答,并且结构清晰。可能需要分步骤解释思路,比如: 1. 处理头节点连续需要删除的情况。 2. 使用双指针法,一个指针遍历,另一个记录前驱节点。 3. 或者使用虚拟头节点的方法,简化操作。 这样用户能够逐步理解解的过程。同时,需要确保代码部分正确,用LaTeX格式的行内公式,比如变量名用$x$,而独立公式的话可能不需要,因为目可能不涉及数学公式。但如果有涉及时间复杂度的话,可以用$O(n)$这样的表达。 总结下来,目应该是删除链表中等于给定值的节点,示例明确,然后给思路代码实现。这样就能满足用户的需求了。</think>### 目:删除链表中的指定值节点 **目描述** 给定一个单链表的头节点 `head` 一个整数 `val`,要求删除链表中所有值为 `val` 的节点,并返回新的头节点。 --- #### 示例 **输入** 头节点为 `1 -> 2 -> 6 -> 3 -> 4 -> 5 -> 6`,`val = 6` **输** `1 -> 2 -> 3 -> 4 -> 5` --- #### 解思路 1. **处理头节点** 如果头节点的值等于 `val`,需不断向后移动头节点,直到找到第一个值不等于 `val` 的节点。 2. **遍历链表** 使用两个指针 `prev`(前驱节点) `curr`(当前节点)遍历链表: - 若 `curr.val == val`,则将 `prev.next` 指向 `curr.next`,跳过当前节点。 - 否则,移动 `prev` `curr` 至下一节点。 --- #### 代码实现 ```python class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def removeElements(head: ListNode, val: int) -> ListNode: # 处理头节点连续为val的情况 while head and head.val == val: head = head.next if not head: return None prev, curr = head, head.next while curr: if curr.val == val: prev.next = curr.next else: prev = prev.next curr = curr.next return head ``` --- #### 复杂度分析 - 时间复杂度:$O(n)$,只需遍历链表一次。 - 空间复杂度:$O(1)$,仅使用常数额外空间。 --- #### 提示 - 使用**虚拟头节点**(Dummy Node)可以避免单独处理头节点被删除的情况,代码更简洁。尝试优化上述代码!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值