NULL 指针 - 无重复字符的最长子串

NULL 指针 - 无重复字符的最长子串

1. NULL 指针

标准定义了 NULL 指针,它作为一个特殊的指针变量,表示不指向任何东西。要使一个指针变量为 NULL,你可以给它赋一个零值。为了测试一个指针变量是否为 NULL,你可以将它与零值进行比较。之所以选择零这个值是因为一种源代码约定。就机器内部而言,NULL 指针的实际值可能与此不同。在这种情况下,编译器将负责零值和内部值之间的翻译转换。

NULL 指针的概念是非常有用的,因为它给了你一种方法,表示某个特定的指针目前并未指向任何东西。例如,一个用于在某个数组中查找某个特定值的函数可能返回一个指向查找到的数组元素的指针。如果该数组不包含指定条件的值,函数就返回一个 NULL 指针。这个技巧允许返回值传达两个不同片段的信息。首先,有没有找到元素?其次,如果找到,它是哪个元素?

尽管这个技巧在 C 程序中极为常用,但它违背了软件工程的原则。用一个单一的值表示两种不同的意思是件危险的事,因为将来很容易无法弄清哪个才是它真正的用意。在大型的程序中,这个问题更为严重,因为你不可能在头脑中对整个设计一览无余。一种更为安全的策略是让函数返回两个独立的值:首先是个状态值,用于提示查找是否成功;其次是个指针,当状态值提示查找成功时,它所指向的就是查找到的元素。

对指针进行解引用操作可以获得它所指向的值。但从定义上看,NULL 指针并未指向任何东西。因此,对一个 NULL 指针进行解引用操作是非法的。在对指针进行解引用操作之前,你首先必须确保它并非 NULL 指针。

如果对一个 NULL 指针进行间接访问会发生什么情况呢?它的结果因编译器而异。在有些机器上,它会访问内存位置零。编译器能够确保内存位置零没有存储任何变量,但机器并未妨碍你访问或修改这个位置。这种行为是非常不幸的,因为程序包含了一个错误,但机器却隐匿了它的症状,这样就使这个错误史加难以寻找。

在其他机器上,对 NULL 指针进行间接访问将引发一个错误,并终止程序。宣布这个错误比隐藏这个错误要好得多,因为程序员能够更容易修正它。

如果所有的指针变量 (而不仅仅是位于静态内存中的指针变量) 能够被自动初始化为 NULL,那实在是件幸事,但事实并非如此。不论你的机器对解引用 NULL 指针这种行为作何反应,对所有的指针变量进行显式的初始化是种好做法。如果你已经知道指针将被初始化为什么地址,就把它初始化为该地址,否则就把它初始化为 NULL。风格良好的程序会在指针解引用之前对它进行检查,这种初始化策略可以节省大量的调试时间。

2. 无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。

示例 1:

输入:"abcabcbb"
输出:3 
解释:因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入:"bbbbb"
输出:1
解释:因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入:"pwwkew"
输出:3
解释:因为无重复字符的最长子串是 "wke",所以其长度为 3。你的答案必须是<font color=blue>**子串**</font>的长度,"pwke" 是一个子序列,不是子串。

2.1 滑动窗口 + 直方图 (Histogram)

字符串 s

在这里插入图片描述

从左侧开始遍历 s,以 i 标记窗口左侧,j 标记窗口右侧,初始时 i=0, j=0,即开头 a 所在的位置,窗口大小为 1。然后将 j 右移,逐步扩大窗口,依次经过 b, c, d,窗口内均无重复字符,继续右移 j

在这里插入图片描述

j 移动到 d 后面的 a 所在位置时,对应字符 a 在窗口中已存在,此时,窗口大小为 5,去除当前重复的一位,窗口大小为 4。此时窗口内的字符串 abcd

在这里插入图片描述

找到窗口中已存在的该字符所在位置,并将 i 移动到该位置下一位置。

在这里插入图片描述

此时为第二个窗口。

在这里插入图片描述

继续重复之前的操作,直到 j 移动到字符串最后一位停止。

int lengthOfLongestSubstring(char * s)
{
	int len_s = 0;
	char *ps = s;
	int histogram_table[128] = { 0 };
	int right_idx = 0, left_idx = 0;
	int len_subs = 0, len_tmp = 0;

	if (NULL == s)
	{
		return 0;
	}

	len_s = strlen(s);
    
    // empty string
	if (0 == len_s)
	{
		return 0;
	}

	right_idx = 0;
	left_idx = 0;
	for (right_idx = 0; right_idx < len_s; right_idx++)
	{
		if (0 != histogram_table[ps[right_idx]])
		{
			if (histogram_table[ps[right_idx]] - 1 >= left_idx)
			{
				left_idx = histogram_table[ps[right_idx]] - 1 + 1;
			}
		}

		len_tmp = right_idx - left_idx + 1;
		if (len_tmp > len_subs)
		{
			len_subs = len_tmp;
		}

		histogram_table[ps[right_idx]] = right_idx + 1;
	}

	return len_subs;
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章