数据结构与算法--基础及常用要素

  1. 数据结构

一、数组

初始化:

int n = 5;  

int[] array = new int[n];

或者 int[] nums = {1,2,3,4,5};        

支持取值、赋值、遍历(for循环即可)、长度length。

数组转字符串:Arrays.toString(nums);

整数数字排序:Arrays.sort(nums);

二、字符串

1. String类型:

        长度length(),支持charAt(index)取字符;

字符串转字符序列(便于for循环取字符):for(char c : str.toCharArray())或者直接赋值出一个字符序列char[] c = str.toCharArray();

2. StringBuffer类型:

        初始化:StringBuffer s = new StringBuffer();

  1. append()拼接到字符串末尾;
  2. insert(index,"sss"),指定位置插入字符串;
  3. replace(index1,index2,"sss"),使用sss替代含index1和index2的字符串;
  4. delete(index1,index2),删除含index1和index2的字符串;
  5. reverse(),翻转字符串;
  6. toString()转为不可变字符串;
  7. deleteCharAt(index) 删除指定字符,一般是删除最后一个字符:deleteCharAt(sb.length()-1)

三、线性表和链表

1. 栈:

        初始化:Stack<Integer> stack = new Stack<>();

  1. 入栈:push(value);顶部入
  2. 出栈:pop();顶部出
  3. 查看栈顶元素:peek()或者top();
  4. 判断栈是否为空:isEmpty()。
2. 队列:

        初始化:Queue<Integer> queue = new LinkedList<>();

                        Duque<Integer> queue = new ArrayDeque<>();

                Java Deque(双端队列)介绍与使用_java双端队列默认使用-CSDN博客

                Java ArrayDeque 与 LinkedList 的区别?-CSDN博客

  1. 入列:offer(value);尾部入
  2. 出列:poll();头部出
  3. 查看队首元素:peek();
  4. 判断队列是否为空:isEmpty();
  5. 查看队列大小:size()。
3. LinkedList

        基本元素是节点ListNode。

        初始化:ListNode head = new ListNode(value);

四、Map、Set和List

1. Map(二维):键不可重复、值可重复,无序    存储映射关系

        0-1. 初始化为一个实例:

                Map<类型,类型> map = new HashMap<>()

        0-2. 初始化(不做实例化):

                Map<类型,类型> map = null

        1. 添加键值对:(修改指定key的值是put直接覆盖)

                put(key,value)

        2. 移除键值对:

                remove(key)

 map轮询器:for(Map.Entry<Character,Integer> entry : map.entrySet())

读取轮询到的元素的key:entry.getKey();

读取轮询到的元素的value:entry.getValue();

java 找出字符串中出现最多的字符_mob64ca12f09e0c的技术博客_51CTO博客

        3. 获取指定key的值:

                map.get(key)

        4. 确认map中是否包含某个key:

                map.containsKey(key)

        5. 确认map中是否包含某个value:

                map.containsValue(value)

        6. 确认map是否为空

                isEmpty()、size()==0

2. Set(一维):元素不可重复,无序      存储不重复元素   

        0. 初始化:

                Set<类型> set = new HashSet<>()

        1. 添加元素:改值是remove+add组合

                add(value)

        2. 移除元素:

                remove(value)

        3. 确认set中是否包含某个元素:set中元素无序,无法获取出来,只需要做是否有的对比

                contains(value)

        4. 确认set是否为空

                isEmpty()、size()==0                

                        https://blog.51cto.com/u_16213408/9372741

3. List(一维):元素可重复,有序    存储有序可重复元素

        初始化:

                List<类型> list = new ArrayList<>()

        添加元素:添加到列表最后位置

                add(value)

        指定位置添加元素:

                add(index,value),其他已有元素均后移

        指定位置修改元素:

                set(index,value)

        移除指定位置的元素:

                remove(index)   用时需谨慎,容易报异常

        获取指定位置的元素:

                get(index)

        获取指定元素的位置:没有则返回-1

                ArrayList.indexOf(value)

        确认list中是否包含某个元素:

                contains(value)

        确认list是否为空

                isEmpty()、size()==0

五、树

1. 二叉树

        基本元素是树节点node。

        深度优先搜索,递归或非递归(栈)。

2. 二叉堆

算法

一、查找、排序、遍历:

1. 数组:

冒泡。。。。

2. 二叉树:

2-1. 先序遍历(根--左--右)

递归:递归的是操作,按照(中:直接取值;左:递归;右:递归),然后将下边界条件标出在递归函数最前部先判断。

2-2. 中序遍历(左--根--右)

递归:递归的是操作,按照(左:递归;中:直接取值;右:递归),然后将下边界条件标出在递归函数最前部先判断。

迭代:主要思路是遇左即压入栈,遇叶子节点(理解为触及三角形下边)则弹出但不一定遍历完成,遇右则直接跟着根节点遍历。

2-3. 后序遍历(左--右--根)

递归:递归的是操作,按照(左:递归;右:递归;中:直接取值),然后将下边界条件标出在递归函数最前部先判断。

迭代:主要思路是,遇左先压入自己,处理左;返回自己取值,再判断是否有右,有则不取自己值重压回,先处理右,右处理完用其值做边界标位表示(右)已经处理过了,最终的边界位上边界即root为空,表示可以跳出整个遍历的循环了。

二、递推法:

        思路:一半是通过前边计算得来的一些计算项来得出序列中的指定项的值。其思想是把一个复杂庞大的计算过程转化为简单过程的多次重复。

三、递归法:

        思路:程序调用自身。其思想是把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。

        一般来说,递归需要有边界条件、递归前进段和递归返回段。

        当边界条件不满足时,递归前进;

        当边界条件满足时,递归返回。

四、分治法:

        思路:分治法是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。

        利用该问题分解出的子问题的解可以合并为该问题的解;

        该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。

递归和分治的区别:

 相同点:都使用了“分而治之”的思想。

不同点:递归法是函数调用自身,分治法是通过不同函数来解决子问题。(所以,递归法子问题解决过程与原问题相似,而分治法子问题相对独立)(递归法需要较多函数调用,可能导致栈溢出,而分治法通过将问题分解成相互独立的子问题,可以更有效地解决问题)。

应用场景:

        递归法:可用于 “计算阶乘” 、“汉诺塔问题” 、“斐波那契数列” 等;

        分治法:可用于 “快速排序”、“归并排序” 、 “大整数乘法” 等。

五、动态规划:最优化模型。当前解由 历史解 组合出来

        思路:其基本思想是,将原问题分解为相似的子问题,在求解的过程中通过子问题的解求出原问题的解。用于求解包含重叠子问题的最优化问题的方法。

递归和动态规划的区别:

递归是一种解决问题的办法,它通过将问题分解为较小的子问题来解决,递归的关键在于如何将问题分解,以及如何利用已经解决的子问题来解决更大的问题,递归的主要特点是:

  • 一个或多个基本情况,这些情况可以直接得到解答;
  • 一个递归函数,该函数将问题分解为较小的子问题并递归的解决这些子问题;
  • 递归停止的条件,即当所有基本情况都被解决时,递归停止。

动态规划时一种解决优化问题的方法,它通过将问题分解为较小的子问题,并解决这些子问题来解决问题。动态规划的关键在于如何将问题分解以及如何利用已经解决的子问题来解决更大的问题,动态规划的主要特点是:(目前可以理解为递归(也有可能不是递归,还没有遇见)+记忆存储)

  • 一个或多个基本情况,这些情况可以直接得到解答;
  • 一个动态规划函数,该函数将问题分解为较小的子问题,并递归地解决这些子问题;
  • 一个存储结构,用于存储已解决的子问题的解答,以避免重复计算;
  • 动态规划停止的条件,即当所有基本情况都被解决时,动态规划停止。

六、回溯法:所有解(解空间探索)

  1. 思路:在包含问题的所有解的解空间树深度优先搜索。从根节点出发深度探索解空间树。
  2. 当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。(其实回溯法就是对隐式图的深度优先搜索算法);
  3. 若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。 而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束。

七、贪心算法:难点:选出最优量度标准。最优解

  1. 思路,一步一步进行,常以当前情况为基础根据某个优化测度做最优选择,而不考虑各种可能的整体情况。虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪婪法不要回溯。
  2. 其核心是根据题意选取一种量度标准,然后将这多个输入排成这种量度标准所要求的顺序,按这种顺序一次输入一个量,如果这个输入和当前已构成在这种量度意义下的部分最佳解加在一起不能产生一个可行解,则不把此输入加到这部分解中。这种能够得到某种量度意义下最优解的分级处理方法称为贪婪算法
  3. 对于一个给定的问题,往往可能有好几种量度标准。初看起来,这些量度标准似乎都是可取的,但实际上,用其中的大多数量度标准作贪婪处理所得到该量度意义下的最优解并不是问题的最优解,而是次优解。因此,选择能产生问题最优解的最优量度标准是使用贪婪算法的核心。

八、迭代法:

九、二分法 关键词 O(logN)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值