随笔分类 - C++
摘要:1、如何判断一个链表是不是有环? 2、如果链表为存在环,如果找到环的入口点?这个算是一个比较老的题目了,之前就看到过,一般通用的做法就是弄两个指针,一个走得快一点,一个走得慢一点。一般是弄一个走一步,一个走两步。这样如果他们相遇,则说明有环。那么在有环的基础上,怎么找到这个环的入口呢,一般网上也会给出解释,可能是我的理解力比较底,网上的解释中,总是用移动了s步,又是长度的,总是弄的我很晕,于是,给出我自己的解释好了,所有的都用移动了多少步来说明。走一步的指针叫slow,走两步的叫fast。相遇的时候,slow共移动了s步,fast共移动了2s步,这个是显而易见的。定义a如下: 链表头移动a步.
阅读全文
摘要:题目:有一个复杂链表,其结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任一结点或者NULL。其结点的C++定义如下:struct ComplexNode{ int value; ComplexNode* pNext; ComplexNode* pSibling;}; 请完成函数ComplexNode* Clone(ComplexNode* pHead),以复制一个复杂链表。 思路: 一般复制一个简单链表就这么遍历一遍就好了,这个复杂链表,比简单链表多的地方就在于多了一个sibling的指针,也就是说在建立完简单链表之后,如何在新的...
阅读全文
摘要:题目:用递归颠倒一个栈。例如输入栈{1, 2, 3, 4, 5},1在栈顶。颠倒之后的栈为{5, 4, 3, 2, 1},5处在栈顶。个人并不觉得这道题设计的有多么好,纯粹就属于没事卖弄技巧的那种,蛋疼的用递归来颠倒一个栈,又浪费时间又浪费空间。解法的思想其实很简单,那么就是你要我颠倒栈,那么我就先把第一个元素保存了,然后弹出其余所有的元素,然后把第一个元素压进去,然后按原来的顺序,压入被弹出的元素,得到的就是 2 3 4 5 1, 2在栈顶,接着用对于前四个,用同样的方法,最后终于颠倒了。void reverseStack(stack<T>& s){ int count
阅读全文
摘要:题目的意思很简单,比如说有数组[1,6,9,2,1,5,15,20],那么满足上述条件的元素为1,15,20。暴力的方法就是从左到右进行遍历,到达某个数字后,在从0开始遍历到当前下标,找出最大的,再从当前下标遍历到尾,找出最小的,然后根据题意比较一下,这个算法为O(n^2)。比较简单的算法就是利用一下额外的空间,保存一下,每个元素右侧的最小值,或者左侧的最大值,在反向遍历一次。举个例子。就如[1,6,9,2,1,5,15,20],如果我们要找到该数组右侧的最小值,则从后向前遍历,20开始,20的右侧的最小值为20,之后15,15右侧的最小值为15,之后5,最小值为5,之后1,最小值为1,那么新
阅读全文
摘要:题目:已经两个已经排好序的数组,找出两个数组合起来的中间大的数字。要求算法复杂度尽可能低。如:x数组:1,7,9,10,30 y数组:3,5,8,11 则中间大数为:8这个题目看似简单,不过要处理起来还是有很多小细节需要注意的。主要思想就是用两个指针同时遍历两个数字,如果第一个数组的值比第二个的小,就第一个数组向前走,否则第二个数组向前走。如果两个的下标等于中间的下标了,那么输出,如果一个数组遍历完成了,还没有到达中间的下标,则说明中间值在另个数组中,标号为 中间下标减去走完的数组元素总数。代码如下: #include "stdafx.h"#include <iost
阅读全文
摘要:原文地址: http://blog.csdn.net/wcyoot/article/details/6428248貌似原文说的不是太详细,表示理解之后,在这里重新解释下,同时感谢原文博主提供了这么多题目以及解答。题目:4个人在晚上过一座小桥,过桥时必须要用到手电筒,只有一枚手电筒,每次最多只可以有两人通过, 4个人的过桥速度分别为1分钟、2分钟、5分钟、10分钟,试问最少需要多长时间4人才可以全部通过小桥?抽象: N个人过桥,每个人过桥需要的时间为ti(1<=i<=N).每次最多两个人过桥,并且还要回来一个。求最快过桥时间。输入:每人过桥时间数组,人数(数组元素个数)。输出:最快时
阅读全文
摘要:题目:输入一个整数和一棵二元树。从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径。打印出和与输入整数相等的所有路径。例如 输入整数22和如下二元树 10 / \ 5 12 / \ 4 7则打印出两条路径:10, 12和10, 5, 7。先序遍历树即可得到结果。算法: PrintPath(TreeNode* pRoot, int sum, const int target) 用来计算,sum为栈中的元素的和,target为目标值。到达一个节点之后计算当前节点和sum的和,如果为target,输出路径返回,如果大于target,则直接...
阅读全文
摘要:以后的算法中可能需要有建树的过程,就把建树的过程,单独弄出来了。通过先序遍历来建立一棵树。如果要建立的树长成这样: 10 / \ 6 14 / \ / 4 8 12那么输入则是应该是这样 10 6 4 # # 8 # # 14 12 # # # 应该是每一个值成为一行,而不是我这样把所有的值都写成一行。他的规则就是,一个先序遍历的过程,先10,再6,在4,在NULL,在NULL,在8,在14,在12,在NULL,NULL,NULL#include <iostream>using namespace std;struct TreeNode{ int dat...
阅读全文
摘要:原文地址: http://blog.csdn.net/wcyoot/article/details/6428297题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。 比如将二元查找树 10 / \ 6 14 / \ / \ 4 8 12 16转换成双向链表4=6=8=10=12=14=16。很明显我们可以知道 中序遍历 一遍二叉查找树就可以得到一个递增的序列。同样,只要中序遍历一下儿茶查找数,调整一下左孩子指针和右孩子指针的指向,就可以得到一个双向链表。代码中的pListHead和pListLast的初始值都是NULL,其中...
阅读全文
摘要:在博客园看到这片文章: http://www.cnblogs.com/MikeZhang/archive/2012/10/26/swapPtr20121026.html的标题,就想自己实现下任务就是将两个指针进行交换,自己也实现了一下,记录一下,如果要看解释,还是去原帖吧。第一种方法就是用二级指针,第二种方法就是用 指针引用。代码如下:#include "stdafx.h"#include <iostream>using namespace std;void swap_point1(int **p1, int **p2){ int* temp = *p1; *p
阅读全文
摘要:没啥太多技巧,反转就好了。单链表的时候要注意,while中不能将pCur的next指向NULL,否则的话,pNext的next就白指了。#include "stdafx.h"#include <iostream>#include<cstring>#include <vector>#include <assert.h>using namespace std;struct ListNode{ int m_key; ListNode* next;};void createList(ListNode* &pHead){ pHe
阅读全文
摘要:自己保存一下,建立链表的程序,省的以后每次建立链表的时候,还需要重新在写。通过下面的代码,建立的链表节点数为10,每个节点保存的数为其下标即:0-9这里要注意一点,在void createList(ListNode* &pHead)的时候,用的是指针引用,因为在main中head并没有开辟空间,如果在createList中为pHead开辟空间的时候,main中的head依旧还是指向NULL的。如果在main中为head开辟了空间的话,就不需要用指针的引用了。道理很简单,就和你传int参数是一个道理。createList中的pHead是形参,也就是说pHead的地址和main中head的
阅读全文
摘要:原文地址: http://blog.csdn.net/jackyliujin/article/details/7581727情况1. 节点只有left/right,没有parent指针,root已知情况2. root未知,但是每个节点都有parent指针情况3. 二叉树是个二叉查找树,且root和两个节点的值(a, b)已知--------------------------------------------------------------------------------虽然情况一是第一个情况,但是看上去比较复杂,我们放到最后来说,先从第二个情况开始说。 10 /\ 6 14 /\
阅读全文
摘要:题目:输入n个整数,输出其中最小的k个。例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。如果这些数字,是放在数组中给出的话,直接建立小顶堆,然后输出前k个就好了。 时间复杂度 kLog(n),建立堆log(n),共建k次void heapAdjust(int* a,int s, int m){ int temp = a[s]; for(int j=2*s+1; j<=m; j=j*2+1) { if(j<m && a[j] > a[j+1]) j++; if(temp<=a[j]) ...
阅读全文
摘要:#include "stdafx.h"#include <iostream>#include <assert.h>using namespace std;//对于a来说,除了a[s]之外均满足大顶堆的定义// 该函数将下标 s到m 调整为大顶堆void heapAdjust(int* a,int s, int m){ int temp = a[s]; // 下标从0开始,则两个孩子分别为 2*i+1 和 2*i+2 for(int j=2*s+1; j<=m; j=j*2+1) { // 执行完成后j中保存了两个孩子中较大的孩子的下表 // .
阅读全文
摘要:题目:输入一个单向链表,输出该链表中倒数第k个结点。链表的倒数第0个结点为链表的尾指针。链表结点定义如下:struct ListNode { int m_nKey; ListNode* m_pNext; };两个方法,第一个先遍历,获得链表总共的长度,这样就知道从head到达倒数第k个需要移动多少次,从头在移动一遍。第二个,两个指针,第二个比第一个多移动k次之后,两个指针再一起移动,这样两个指针之间始终有k个距离,当第二个指针移动到NULL的时候,第一个指针所指向的就是倒数第K个。代码如下:template <typename T>struct ListNode{ T m_k...
阅读全文
摘要:题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则输出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。这题貌似也是一道很常见的题目,主要思路就是如下的这段话:我们以三个字符abc为例来分析一下求字符串排列的过程。首先我们固定第一个字符a,求后面两个字符bc的排列。当两个字符bc的排列求好之后,我们把第一个字符a和后面的b交换,得到bac,接着我们固定第一个字符b,求后面两个字符ac的排列。现在是把c放到第一位置的时候了。记住前面我们已经把原先的第一个字符a和后面的b做了交换,为了保证这次c仍然是和原先处在第一位置的a交换,我们
阅读全文
摘要:传说这是一道知名外企的笔试题但是看了一些文章,都只是单纯的转了那个算法,弱弱的说一句,那个算法中把'\0'写成了'/0',会导致在while ('/0' != *pTemp) { hashTable[*pTemp] = 1; ++ pTemp; } 这一步的时候,一直循环下去,直到系统中断。不过调试的时候发现了一个很有意思的事情,就是之前pTemp之前是指向aeiou,这就是传入的第二个参数,当遍历完这个参数之后,pTemp会继续指向栈中的下一个地址,也就是第一个参数they are students的地址,这个...
阅读全文
摘要:原文地址:http://www.51testing.com/html/72/n-221172.html传说常见的一个笔试题:不使用中间变量求const字符串长度,即实现求字符串长度库函数strlen函数。函数接口声明如下:int strlen(const char *p); 思路分析: 在字符串中通常可以利用最后一个结束符’\0’,但此处参数为const,只读,那么我们不能打他的主意。 函数运行过程中不占用内存基本不可能,除非都使用了寄存器。“不使用中间变量”只是说程序员不能显示的申请内存而已,即不能有局部变量或者动态内存申请。 如果函数自动申请栈内存或者使用寄存器存储变量,或者使用立...
阅读全文
摘要:主要是为了记录最后一种神奇的方法。原文地址:http://www.cnblogs.com/xianghang123/archive/2011/08/24/2152408.html这是一个很有意思的问题,也是在面试中最容易被问到的问题之一。这个问题有个正式的名字叫Hamming_weight,而且wikipedia上也提供了很好的位运算解决的方法,这个下面也会提到。解决这个问题的第一想法是一位一位的观察,判断是否为1,是则计数器加一,否则跳到下一位,于是很容易有这样的程序。int test(int n){ int count=0; while(n != 0){ if(n...
阅读全文

浙公网安备 33010602011771号