剑指offer

二叉树是否是其子结构

从根节点开始,不是,看左节点,再看有节点

链表合并


翻转链表

链表找入口

链表蛇形打印

数组中重复的数字


二维数组找target

替换空格

两个指针 一个指向末尾,一个指向替换后的字符串的末尾


逆序输出链表

栈,加递归


构建乘积数组,遍历两次,从头然后从尾部


不用运算法则做加法


求 1+...+n

&&的短路原理


股票的最大利润,找到当前最小值,和当前最大差值,进行替换


圆圈中最后剩下的数字


扑克牌中的顺子,判断是否连续,中间差不要大于王的个数,或者直接小于四


n个骰子的点数

递归


反轉句子中单词的顺序



队列的最大值(窗口)

两个列表,一个缓存窗口,一个缓存最终最大值的变量,窗口需要满足是一个两端的队列,最大值在0,如果超过size大小,则pop 0,如果新来的比原有缓存窗口的值大,在pop,


和为s的两个数字之乘积最小

遍历两次,拿到所有组合放到ls中,取ls[0]

搜索旋转排序数组  logn 就是二分的思想

数组不存在重复数字

举例子观察left和right取等号不?,先找第一遍分界点,logn,再二分查找,logn

(数组是否是重复的)

找到中间位置

考虑元素重复 加边界条件 如下


数组中数字出现的次数


顺时针打印矩阵

行列大于2倍的start

二叉树的深度

递归调用函数也需要加self

平衡二叉树



二叉搜索树k大的节点

二叉搜索树中左节点小于根节点,右节点大于根节点,通过中序遍历即可排序,再取第k

大的节点

排序数组中查找数字出现次数

classSolution:

    defGetNumberOfK(self, data, k):

        # write code here

        count =len(data)

        i =0

        forj inrange(count):

            ifdata[j] ==k:

                i +=1

        returni

排序数组,想到二分查找,先找到第一个存在的k,在找到最后一个存在的k,找到中间位置,若等于该数字,判断前一个是不是该数字,是的话,再继续二分查找,直到找到等于该数字,且前一个不是该数字的位置。

递增排序数组中缺失的数字,log(n)的解决方案,遍历用总和减去目前的和

log(n)考虑转换题目为找出第一个值与下标不相等的元素

num[middle] != middle

链表找环,

思路一 两个链表接起来,找到相同的点

思路二,先遍历一遍,确定两个链表的长度,然后求出差值,长的链表先走差值的歩数


数组中的逆序对

mergesort


逆序对

public class Solution {

    public int InversePairs(int [] array) {

        if(array==null||array.length==0)

        {

            return 0;

        }

        int[] copy = new int[array.length];

        for(int i=0;i<array.length;i++)

        {

            copy[i] = array[i];

        }

        int count = InversePairsCore(array,copy,0,array.length-1);//数值过大求余

        return count;


    }

    private int InversePairsCore(int[] array,int[] copy,int low,int high)

    {

        if(low==high)

        {

            return 0;

        }

        int mid = (low+high)>>1;

        int leftCount = InversePairsCore(array,copy,low,mid)%1000000007;

        int rightCount = InversePairsCore(array,copy,mid+1,high)%1000000007;

        int count = 0;

        int i=mid;

        int j=high;

        int locCopy = high;

        while(i>=low&&j>mid)

        {

            if(array[i]>array[j])

            {

                count += j-mid;

                copy[locCopy--] = array[i--];

                if(count>=1000000007)//数值过大求余

                {

                    count%=1000000007;

                }

            }

            else

            {

                copy[locCopy--] = array[j--];

            }

        }

        for(;i>=low;i--)

        {

            copy[locCopy--]=array[i];

        }

        for(;j>mid;j--)

        {

            copy[locCopy--]=array[j];

        }

        for(int s=low;s<=high;s++)

        {

            array[s] = copy[s];

        }

        return (leftCount+rightCount+count)%1000000007;

    }

}

字符串中第一个只出现一次的字符,python采用count

hash 第一遍求出出现的次数,第二遍挑出等于1的

classSolution:

    defFirstNotRepeatingChar(self, s):

        # write code here

        index =0

        iflen(s) ==0:

            return-1

        else:

            forx ins:

                ifs.count(x) ==1:

                    returnindex

                index +=1

字符流中第一个不重复的数字,是一个不断迭代不断更新的过程,通过两个函数方法实现,一个更新s和dict, 一个检查


寻找丑数

第一种写一个判断是不是丑数的函数

% 2,3,5=0 则整除2.3,5最终为1则为丑数,挑出第1500个每个数字都需要计算


第二种通过增加辅助数组减少换取时间上的效率

三个指针开始移动乘以2,3,5 取最小


最长不含重复字符的子字符串

class Solution:

    def lengthOfLongestSubstring(self, s):

        """        :type s: str

        :rtype: int

        """        start=0

        maxLength=0

        usedChar={}

        foriin range(len(s)):

            ifs[i]inusedCharandstart<=usedChar[s[i]]:

                start=usedChar[s[i]]+1else:

                maxLength=max(maxLength,i-start+1)

            usedChar[s[i]]=i


        return maxLength

动态规划的思路

通过一个trcik 定义一个26长度的数组,初始-1,来记录上一次出现该字符的位置

如果没出现过或者上次出现过的距离大于当前最大长度

则当前长度++

否则上次出现过的最大距离等于当前长度再与最大长度作对比进行替换


礼物的最大价值

动态规划,python版本,基于递归的思路用大量重复计算,采用循环则代码效率会高很多,为了缓存中间结果需要辅助数组。

def getMaxValue1(self,array,rows,cols):

        # write code hereifarray==[]orrows<=0orcols<=0:

            return 0

        maxValues=[[0foriinrange(cols)]forjin range(rows)]

        foriin range(rows):

            forjin range(cols):

                left=0

                up=0

                ifi>0:

                    #如果行号大于0,说明它上面有数字up=maxValues[i-1][j]

                ifj>0:

                    #如果列号大于0,说明它左边有数字left=maxValues[i][j-1]

                maxValues[i][j]=max(up,left)+array[i*cols+j]

        returnmaxValues[rows-1][cols-1]

通过规律可以发现只添加一个长度等于列的数组即可

def getMaxValue2(self, array, rows, cols):

        # write code hereifarray == []orrows <= 0orcols <= 0:

            return 0

        maxValues=[0foriin range(cols)]

        foriin range(rows):

            forjin range(cols):

                up=0

                left=0

                ifi>0:

                    #如果行号大于0,说明它上面有数字。up仍为当前列的maxValueup=maxValues[j]

                ifj>0:

                    #如果列号大于0,说明它左边有数字。left=maxValues[j-1]

                maxValues[j]=max(up,left)+array[i*cols+j]

        returnmaxValues[cols-1]

把数字都翻译成字符串

采用动态规划的思路,从最小的开始计算

通过归纳定义一个函数fi=fi+1 +g*fi+2,如果第i位置和i+1位置的和在10-25以内的时候,g=1否则为零

把数组排成最小的数

先把数字转换成字符串,然后在函数中定义比较规则,在采用qsort,最终的复杂度等于qsort 为O(nlogn)比拼接所有组合的n!要小

sorted(iterable, cmp=None, key=None, reverse=False)

iterable -- 可迭代对象。 cmp -- 比较的函数,这个具有两个参数,参数的值都是从可迭代对象中取出,此函数必须遵守的规则为,大于则返回1,小于则返回-1,等于则返回0。 key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。 reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)

数字序列中的某一位数字

找到规律发现对应的数字是什么,判断对应的数字是哪个区间内呢,10, 180,2700,在找到这个区域开始的位置,0,10,100然后取得该位置for i <biginnumer, numbers/10

1~n中1出现的次数

暴力解法


连续子数组的最大和

当前最大和的初始值应为一个负数  greatSum=float('-inf')

数据流中的中位数

一遍排序,一遍取中位数

偶数的时候一个为下标,一个为下标-1


最小的k个数

可以最大堆,或者快排

快排的partion


数组中出现一半的数字

快排取中位数



字符串的排列

python itertools

combinations方法重点在组合,permutations方法重在排列。

combinations和permutations返回的是对象地址,原因是在python3里面,返回值已经不再是list,而是iterators(迭代器), 所以想要使用,只用将iterator 转换成list 即可


java或者cpp采用递归的思路,分成两部分,一部分是第一个字符,另一部分是后边所有字符,第一个字符和后边所有字符来替换

写java 包的引用与熟练,采用java 用下标ij作为指针。

重建二叉树

要求节点不能重复,先序遍历,加中序遍历

找到根节点,然后知道左右两颗子树通过递归实现

public class Solution {

    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {

        int length=pre.length;

        if(length==0){

            return null;

        }

        if(length==1){

            TreeNode flag = new TreeNode(pre[0]);

            //flag.val=pre[0];

            return flag;

        }else{

            TreeNode flag = new TreeNode(pre[0]);


        int gen=0 ;

        for(int i=0;i<in.length;i++)

        {

            if(in[i]==pre[0])

            {

                gen=i;

                break;

            }

        }

          int[] pre_left=new int[gen];

        int[] pre_right=new int[length-gen-1];

        int[] in_left=new int[gen];

        int[] in_right=new int[length-gen-1];

        for(int i=0;i<gen;i++)

        {

            in_left[i]=in[i];

            pre_left[i]=pre[i+1];

        }

        for(int i=gen+1;i<length;i++)

        {

            in_right[i-gen-1]=in[i];

            pre_right[i-gen-1]=pre[i];

        }

            flag.left=reConstructBinaryTree(pre_left,in_left);

            flag.right=reConstructBinaryTree(pre_right,in_right);

            return flag;

        }

    }

python 采用index函数找到下标


序列化二叉树

从先序遍历开始 ,采用递归的思路,序列化是拼接成字符串

  defSerialize(self, root):

        s =""

        s =self.recursionSerialize(root, s)

        returns


    defrecursionSerialize(self, root, s):

        if(root isNone):

            s ='$,'

            returns

        s =str(root.val) +','

        left =self.recursionSerialize(root.left, s)

        right =self.recursionSerialize(root.right, s)

        s +=left +right

        returns

解码的时候,python先用split拿到现在的所有字符,cpp可以做成流式处理

root需要通过TreeNode来生成


二叉搜索树与双向链表

思路1加一个O(n)的数组来存储中序遍历的值,然后转成双向排序链表

self.attr[:-1] 

思路二:递归,将特定节点的左指针指向其左子树中的最后子节点,将其右指针指向其右子树中的最左子节点,依次递归,调整好全部节点的指针指向。拿到phead为最小值,其他节点的指针调整为递归思路。即根节点指向左子树的最大值,右子树最小值


二叉树的镜像

左右子节点依次交换顺序


对称的二叉树

需要把空指针考虑进来

对比节点的左右子节点是否一致


顺时针打印矩阵

循环的条件是start*2小于column和row

出发的点是相同的start。第一步总是有的,第二步的前提条件是终止行号大于起始行号,第三部的条件是,终止行号大于起始行号,且终止列号大于起始列号,第四部是终止行号比截止行号大2,且列号大于终止列号


包含min函数的栈

java peek 不弹出,

思路定义一个存最小值的栈


栈的压入与弹出

判断弹出的顺序是不是压栈的序列,建立辅助栈,情况如下,如直接相同,则为压入立即弹出,如果辅助栈栈顶存在的与要pop的相同,则弹出,否则判断压入栈时候还有值,有的话加入辅助栈,直到所有的值压入,判断是否是其弹出的序列。

从上到下打印二叉树

不分行的时候


分行打印

采用广度优先遍历一棵树的时候,采用队列

分行打印返回一个二维列表


之字形打印

分词奇数和偶数的列表进行存储

二叉搜索树的后序遍历序列

想到递归,特征为 左子树小于根节点,右子树大于根节点


二叉树和为某一值的路径

从根节点到子节点为一个路径,采用递归,,如果子节点没有左右节点且值等于,则返回,否则为none,



复杂链表的复制

方法1、通过空间换时间,通过一个hash表,记录配对信息放在hash表

方法2、分成三步骤,1、复制每个节点对应的下一个节点,然后复制其指向的节点,然后将奇数位置的节点连接起来。

class Solution:

    # 返回 RandomListNodedef Clone(self, pHead):

        # write code hereifpHead==None:

            return None

        self.CloneNodes(pHead)

        self.ConnectRandomNodes(pHead)

        return self.ReconnectNodes(pHead)


    def CloneNodes(self,pHead):

        '''        复制原始链表的每个结点, 将复制的结点链接在其原始结点的后面

        '''        pNode=pHead

        while pNode:

            pCloned=RandomListNode(0)

            pCloned.label=pNode.label

            pCloned.next=pNode.next

            pNode.next=pCloned

            pNode=pCloned.next


    def ConnectRandomNodes(self,pHead):

        '''        将复制后的链表中的克隆结点的random指针链接到被克隆结点random指针的后一个结点

        '''        pNode=pHead

        while pNode:

            pCloned=pNode.next

            ifpNode.random!=None:

                pCloned.random=pNode.random.next

            pNode=pCloned.next

    def ReconnectNodes(self,pHead):

        '''        拆分链表:将原始链表的结点组成新的链表, 复制结点组成复制后的链表

        '''        pNode=pHead

        pClonedHead=pClonedNode=pNode.next

        pNode.next = pClonedNode.next

        pNode=pNode.next

        while pNode:

            pClonedNode.next=pNode.next

            pClonedNode=pClonedNode.next

            pNode.next=pClonedNode.next

            pNode=pNode.next

        returnpClonedHead

方法3、递归法


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容

  • 前言 2. 实现 Singleton 3. 数组中重复的数字 4. 二维数组中的查找 5. 替换空格 6. 从尾到...
    Observer_____阅读 2,926评论 0 1
  • 1.二维数组中的查找 题目描述在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一...
    念人远乡阅读 510评论 0 5
  • 1.在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序...
    甜柚小仙女阅读 425评论 0 1
  • 面试题3——数组中重复的数字 使用LinkedHashMap,有序存放。 面试题4——二维数组中的查找 首先选...
    做自己的Yang光阅读 471评论 0 0
  • 超能陆战队以及所有奋斗在暑期一线的同事们,你们好。我是万能姣韩方姣。 感悟+自省: 1.服务就是要面面俱到。 2....
    万能姣阅读 102评论 0 0