mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-09-26 05:06:42 +08:00
456 lines
27 KiB
HTML
456 lines
27 KiB
HTML
<!DOCTYPE html>
|
||
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
<head>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
|
||
<link rel="icon" href="/static/favicon.png">
|
||
<title>加餐 课后练习题详解.md.html</title>
|
||
<!-- Spectre.css framework -->
|
||
<link rel="stylesheet" href="/static/index.css">
|
||
<!-- theme css & js -->
|
||
<meta name="generator" content="Hexo 4.2.0">
|
||
</head>
|
||
<body>
|
||
<div class="book-container">
|
||
<div class="book-sidebar">
|
||
<div class="book-brand">
|
||
<a href="/">
|
||
<img src="/static/favicon.png">
|
||
<span>技术文章摘抄</span>
|
||
</a>
|
||
</div>
|
||
<div class="book-menu uncollapsible">
|
||
<ul class="uncollapsible">
|
||
<li><a href="/" class="current-tab">首页</a></li>
|
||
</ul>
|
||
<ul class="uncollapsible">
|
||
<li><a href="../">上一级</a></li>
|
||
</ul>
|
||
<ul class="uncollapsible">
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/00 数据结构与算法,应该这样学!.md.html">00 数据结构与算法,应该这样学!</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/01 复杂度:如何衡量程序运行的效率?.md.html">01 复杂度:如何衡量程序运行的效率?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/02 数据结构:将“昂贵”的时间复杂度转换成“廉价”的空间复杂度.md.html">02 数据结构:将“昂贵”的时间复杂度转换成“廉价”的空间复杂度</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/03 增删查:掌握数据处理的基本操作,以不变应万变.md.html">03 增删查:掌握数据处理的基本操作,以不变应万变</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/04 如何完成线性表结构下的增删查?.md.html">04 如何完成线性表结构下的增删查?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/05 栈:后进先出的线性表,如何实现增删查?.md.html">05 栈:后进先出的线性表,如何实现增删查?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/06 队列:先进先出的线性表,如何实现增删查?.md.html">06 队列:先进先出的线性表,如何实现增删查?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/07 数组:如何实现基于索引的查找?.md.html">07 数组:如何实现基于索引的查找?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/08 字符串:如何正确回答面试中高频考察的字符串匹配算法?.md.html">08 字符串:如何正确回答面试中高频考察的字符串匹配算法?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/09 树和二叉树:分支关系与层次结构下,如何有效实现增删查?.md.html">09 树和二叉树:分支关系与层次结构下,如何有效实现增删查?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/10 哈希表:如何利用好高效率查找的“利器”?.md.html">10 哈希表:如何利用好高效率查找的“利器”?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/11 递归:如何利用递归求解汉诺塔问题?.md.html">11 递归:如何利用递归求解汉诺塔问题?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/12 分治:如何利用分治法完成数据查找?.md.html">12 分治:如何利用分治法完成数据查找?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/13 排序:经典排序算法原理解析与优劣对比.md.html">13 排序:经典排序算法原理解析与优劣对比</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/14 动态规划:如何通过最优子结构,完成复杂问题求解?.md.html">14 动态规划:如何通过最优子结构,完成复杂问题求解?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/15 定位问题才能更好地解决问题:开发前的复杂度分析与技术选型.md.html">15 定位问题才能更好地解决问题:开发前的复杂度分析与技术选型</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/16 真题案例(一):算法思维训练.md.html">16 真题案例(一):算法思维训练</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/17 真题案例(二):数据结构训练.md.html">17 真题案例(二):数据结构训练</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/18 真题案例(三):力扣真题训练.md.html">18 真题案例(三):力扣真题训练</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/19 真题案例(四):大厂真题实战演练.md.html">19 真题案例(四):大厂真题实战演练</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/20 代码之外,技术面试中你应该具备哪些软素质?.md.html">20 代码之外,技术面试中你应该具备哪些软素质?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/重学数据结构与算法-完/21 面试中如何建立全局观,快速完成优质的手写代码?.md.html">21 面试中如何建立全局观,快速完成优质的手写代码?</a>
|
||
</li>
|
||
<li>
|
||
<a class="current-tab" href="/专栏/重学数据结构与算法-完/加餐 课后练习题详解.md.html">加餐 课后练习题详解</a>
|
||
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
|
||
<div class="sidebar-toggle-inner"></div>
|
||
</div>
|
||
<script>
|
||
function add_inner() {
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
inner.classList.add('show')
|
||
}
|
||
function remove_inner() {
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
inner.classList.remove('show')
|
||
}
|
||
function sidebar_toggle() {
|
||
let sidebar_toggle = document.querySelector('.sidebar-toggle')
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let content = document.querySelector('.off-canvas-content')
|
||
if (sidebar_toggle.classList.contains('extend')) { // show
|
||
sidebar_toggle.classList.remove('extend')
|
||
sidebar.classList.remove('hide')
|
||
content.classList.remove('extend')
|
||
} else { // hide
|
||
sidebar_toggle.classList.add('extend')
|
||
sidebar.classList.add('hide')
|
||
content.classList.add('extend')
|
||
}
|
||
}
|
||
function open_sidebar() {
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
sidebar.classList.add('show')
|
||
overlay.classList.add('show')
|
||
}
|
||
function hide_canvas() {
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
sidebar.classList.remove('show')
|
||
overlay.classList.remove('show')
|
||
}
|
||
</script>
|
||
<div class="off-canvas-content">
|
||
<div class="columns">
|
||
<div class="column col-12 col-lg-12">
|
||
<div class="book-navbar">
|
||
<!-- For Responsive Layout -->
|
||
<header class="navbar">
|
||
<section class="navbar-section">
|
||
<a onclick="open_sidebar()">
|
||
<i class="icon icon-menu"></i>
|
||
</a>
|
||
</section>
|
||
</header>
|
||
</div>
|
||
<div class="book-content" style="max-width: 960px; margin: 0 auto;
|
||
overflow-x: auto;
|
||
overflow-y: hidden;">
|
||
<div class="book-post">
|
||
<p id="tip" align="center"></p>
|
||
<div><h1>加餐 课后练习题详解</h1>
|
||
<p>专栏虽已结束,但学习不应停止。我看到很多同学依然还在这里学习,一部分同学积极地在留言区和大家分享学习总结和练习题答案。</p>
|
||
<p>我几乎在每个课时的结尾都留下了一道练习题,目的是帮助你检测和巩固本课时的重点内容,抑或是引出后续课时中的内容。在我处理留言的过程中,发现很多同学想要练习题详细解答过程以及答案,所以就有了今天的这一篇加餐内容,希望对你有所帮助。</p>
|
||
<p>接下来我会给出每个课时练习题的解题思路和答案,如果你没有找到对应的练习题答案,那么请你在正课中查找。</p>
|
||
<h4>01 | 复杂度:如何衡量程序运行的效率?</h4>
|
||
<p><strong>【问题】</strong> 评估一下,如下的代码片段,时间复杂度是多少?</p>
|
||
<pre><code>for (i = 0; i < n; i++) {
|
||
for (j = 0; j < n; j++) {
|
||
for (k = 0; k < n; k++) {
|
||
}
|
||
for (m = 0; m < n; m++) {
|
||
}
|
||
}
|
||
}
|
||
</code></pre>
|
||
<p><strong>【解析】</strong> 在上面的代码中:</p>
|
||
<ul>
|
||
<li>第 3~5 行和 6~8 行,显然是一个 O(n) 复杂度的循环。这两个循环是顺序结构,因此合在一起的复杂度是 O(n) + O(n) = O(2n) = O(n)。</li>
|
||
<li>第 2~9 行是一个 for 循环,它的时间复杂度是 O(n)。这个 for 循环内部嵌套了 O(n) 复杂度的代码,因此合在一起就是 O(n ² ) 的时间复杂度。</li>
|
||
<li>在代码的最外部,第 1~10 行又是一个 O(n) 复杂度的循环,内部嵌套了 O(n ² ) 的时间复杂度的代码。因此合在一起就是 O(n ³ ) 的时间复杂度。</li>
|
||
</ul>
|
||
<h4>02 | 数据结构:将“昂贵”的时间复杂度转换成“廉价”的空间复杂度</h4>
|
||
<p><strong>【问题】</strong> 在下面这段代码中,如果要降低代码的执行时间,第 4 行代码需要做哪些改动呢?如果做出改动后,是否降低了时间复杂度呢?</p>
|
||
<pre><code>public void s2_2() {
|
||
int count = 0;
|
||
for (int i = 0; i <= (100 / 7); i++) {
|
||
for (int j = 0; j <= (100 / 3); j++) {
|
||
if ((100-i*7-j*3 >= 0)&&((100-i*7-j*3) % 2 == 0)) {
|
||
count += 1;
|
||
}
|
||
}
|
||
}
|
||
System.out.println(count);
|
||
}
|
||
</code></pre>
|
||
<p><strong>【解析】</strong> 代码的第 4 行可以改为:</p>
|
||
<pre><code>for (int j = 0; j <= (100-7*i) / 3; j++) {
|
||
</code></pre>
|
||
<p>代码改造完成后,时间复杂度并没有变小。但由于减少了一些不必要的计算量,程序的执行时间变少了。</p>
|
||
<h4>03 | 增删查:掌握数据处理的基本操作,以不变应万变</h4>
|
||
<p><strong>【问题】</strong> 对于一个包含 5 个元素的数组,如果要把这个数组元素的顺序翻转过来。你可以试着分析该过程需要对数据进行哪些操作?</p>
|
||
<p><strong>【解析】</strong> 假设原数组 a = {1,2,3,4,5},现在要更改为 a = {5,4,3,2,1}。要想得到新的数组,就要找到 “1” 和 “5”,再分别把它们赋值给对方。因此,这里主要会产生大量的基于索引位置的查找动作。</p>
|
||
<h4>04 | 如何完成线性表结构下的增删查?</h4>
|
||
<p><strong>【问题】</strong> 给定一个包含 n 个元素的链表,现在要求每 k 个节点一组进行翻转,打印翻转后的链表结果。例如,链表为 1 -> 2 -> 3 -> 4 -> 5 -> 6,k = 3,则打印 321654。</p>
|
||
<p><strong>【解析】</strong> 我们给出一些提示。利用链表翻转的算法,这个问题应该很简单。利用 3 个指针,prev、curr、next,执行链表翻转,每次得到了 k 个翻转的结点就执行打印。</p>
|
||
<h4>05 | 栈:后进先出的线性表,如何实现增删查?</h4>
|
||
<p><strong>【问题】</strong> 给定一个包含 n 个元素的链表,现在要求每 k 个节点一组进行翻转,打印翻转后的链表结果。例如,链表为 1 -> 2 -> 3 -> 4 -> 5 -> 6,k = 3,则打印 321654。要求用栈来实现。</p>
|
||
<p><strong>【解析】</strong> 我们用栈来实现它,就很简单了。你可以牢牢记住,<strong>只要涉及翻转动作的题目,都是使用栈来解决的强烈信号</strong>。</p>
|
||
<p>具体的操作如下,设置一个栈,不断将队列数据入栈,并且实时记录栈的大小。当栈的大小达到 k 的时候,全部出栈。我们给出核心代码:</p>
|
||
<pre><code>while (tmp != null && count < k) {
|
||
stack.push(tmp.value);
|
||
tmp = tmp.next;
|
||
count++;
|
||
}
|
||
while (!stack.isEmpty()) {
|
||
System.out.print(stack.pop());
|
||
}
|
||
</code></pre>
|
||
<h4>07 | 数组:如何实现基于索引的查找?</h4>
|
||
<p><strong>详细分析和答案,请翻阅 18 课时例题 1</strong>。</p>
|
||
<h4>08 | 字符串:如何正确回答面试中高频考察的字符串匹配算法?</h4>
|
||
<p><strong>详细分析和解题步骤,请参考 17 课时例题 1。</strong></p>
|
||
<h4>10 | 哈希表:如何利用好高效率查找的“利器”?</h4>
|
||
<p><strong>详细分析和答案,请翻阅 15 课时例题 1</strong>。</p>
|
||
<h4>11 | 递归:如何利用递归求解汉诺塔问题?</h4>
|
||
<p><strong>详细分析和答案,请翻阅 16 课时例题 1</strong>。</p>
|
||
<h4>12 | 分治:如何利用分治法完成数据查找?</h4>
|
||
<p><strong>【问题】</strong> 在一个有序数组中,查找出第一个大于 9 的数字,假设一定存在。例如,arr = { -1, 3, 3, 7, 10, 14, 14 };则返回 10。</p>
|
||
<p><strong>【解析】</strong> 在这里提醒一下,带查找的目标数字具备这样的性质:</p>
|
||
<ul>
|
||
<li>第一,它比 9 大;</li>
|
||
<li>第二,它前面的数字(除非它是第一个数字),比 9 小。</li>
|
||
</ul>
|
||
<p>因此,当我们作出向左走或向右走的决策时,必须满足这两个条件。代码如下:</p>
|
||
<pre><code>public static void main(String[] args) {
|
||
int targetNumb = 9;
|
||
// 目标有序数组
|
||
int[] arr = { -1, 3, 3, 7, 10, 14, 14 };
|
||
int middle = 0;
|
||
int low = 0;
|
||
int high = arr.length - 1;
|
||
while (low <= high) {
|
||
middle = (high + low) / 2;
|
||
if (arr[middle] > targetNumb && (middle == 0 || arr[middle - 1] <= targetNumb)) {
|
||
System.out.println("第一个比 " + targetNumb + " 大的数字是 " + arr[middle]);
|
||
break;
|
||
} else if (arr[middle] > targetNumb) {
|
||
// 说明该数在low~middle之间
|
||
high = middle - 1;
|
||
} else {
|
||
// 说明该数在middle~high之间
|
||
low = middle + 1;
|
||
}
|
||
}
|
||
}
|
||
</code></pre>
|
||
<h4>14 | 动态规划:如何通过最优子结构,完成复杂问题求解?</h4>
|
||
<p><strong>详细分析和答案,请翻阅 16 课时例题 3</strong>。</p>
|
||
<h4>15 | 定位问题才能更好地解决问题:开发前的复杂度分析与技术选型</h4>
|
||
<p><strong>【问题】</strong> 下面的代码采用了两个 for 循环去实现 two sums。那么,能否只使用一个 for 循环完成呢?</p>
|
||
<pre><code>private static int[] twoSum(int[] arr, int target) {
|
||
Map<Integer, Integer> map = new HashMap<>();
|
||
for (int i = 0; i < arr.length; i++) {
|
||
map.put(arr[i], i);
|
||
}
|
||
for (int i = 0; i < arr.length; i++) {
|
||
int complement = target - arr[i];
|
||
if (map.containsKey(complement) && map.get(complement) != i) {
|
||
return new int[] { map.get(complement), i };
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
</code></pre>
|
||
<p><strong>【解析】</strong> 原代码中,第 3 和第 6 行的 for 循环合并后,就需要把 map 的新增、查找合在一起执行。则代码如下:</p>
|
||
<pre><code>private static int[] twoSum(int[] arr, int target) {
|
||
Map<Integer, Integer> map = new HashMap<>();
|
||
for (int i = 0; i < arr.length; i++) {
|
||
int complement = target - arr[i];
|
||
if (map.containsKey(complement) && map.get(complement) != i) {
|
||
return new int[] { map.get(complement), i };
|
||
}
|
||
else{
|
||
map.put(arr[i], i);
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
</code></pre>
|
||
<h4>16 | 真题案例(一):算法思维训练</h4>
|
||
<p><strong>【问题】</strong> 如果现在是个线上实时交互的系统。客户端输入 x,服务端返回斐波那契数列中的第 x 位。那么,这个问题使用上面的解法是否可行。</p>
|
||
<p><strong>【解析】</strong> 这里给你一个小提示,既然我这么问,答案显然是不可行的。如果不可行,原因是什么呢?我们又该如何解决?</p>
|
||
<p>注意,题目中给出的是一个实时系统。当用户提交了 x,如果在几秒内没有得到系统响应,用户就会卸载 App 啦。</p>
|
||
<p>一个实时系统,必须想方设法在 O(1) 时间复杂度内返回结果。因此,一个可行的方式是,在系统上线之前,把输入 x 在 1~100 的结果预先就计算完,并且保存在数组里。当收到 1~100 范围内输入时,O(1) 时间内就可以返回。如果不在这个范围,则需要计算。计算之后的结果返回给用户,并在数组中进行保存。以方便后续同样输入时,能在 O(1) 时间内可以返回。</p>
|
||
<h4>17 | 真题案例(二):数据结构训练</h4>
|
||
<p><strong>【问题】</strong> 对于树的层次遍历,我们再拓展一下。如果要打印的不是层次,而是蛇形遍历,又该如何实现呢?蛇形遍历就是 s 形遍历,即奇数层从左到右,偶数层从右到左。</p>
|
||
<p><strong>【解析】</strong> 这里要对数据的顺序进行逆序处理,直观上,你需要立马想到栈。毕竟只有栈是后进先出的结构,是能快速实现逆序的。具体而言,需要建立两个栈 s1 和 s2。进栈的顺序是,s1 先右后左,s2 先左后右。两个栈交替出栈的结果就是 s 形遍历,代码如下:</p>
|
||
<pre><code>public ArrayList<ArrayList<Integer>> Print(TreeNodes pRoot) {
|
||
// 先右后左
|
||
Stack<TreeNodes> s1 = new Stack<TreeNodes>();
|
||
// 先左后右
|
||
Stack<TreeNodes> s2 = new Stack<TreeNodes>();
|
||
ArrayList<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();
|
||
list.add(pRoot.val);
|
||
s1.push(pRoot);
|
||
while (s1.isEmpty() || s2.isEmpty()) {
|
||
if (s1.isEmpty() && s2.isEmpty()) {
|
||
break;
|
||
}
|
||
if (s2.isEmpty()) {
|
||
while (!s1.isEmpty()) {
|
||
if (s1.peek().right != null) {
|
||
list.add(s1.peek().right.val);
|
||
s2.push(s1.peek().right);
|
||
}
|
||
if (s1.peek().left != null) {
|
||
list.add(s1.peek().left.val);
|
||
s2.push(s1.peek().left);
|
||
}
|
||
s1.pop();
|
||
}
|
||
} else {
|
||
while (!s2.isEmpty()) {
|
||
if (s2.peek().left != null) {
|
||
list.add(s2.peek().left.val);
|
||
s1.push(s2.peek().left);
|
||
}
|
||
if (s2.peek().right != null) {
|
||
list.add(s2.peek().right.val);
|
||
s1.push(s2.peek().right);
|
||
}
|
||
s2.pop();
|
||
}
|
||
}
|
||
}
|
||
return list;
|
||
}
|
||
</code></pre>
|
||
<h4>18 | 真题案例(三): 力扣真题训练</h4>
|
||
<p><strong>【问题】</strong> 给定一个链表,删除链表的倒数第 n 个节点。例如,给定一个链表: 1 -> 2 -> 3 -> 4 -> 5, 和 n = 2。当删除了倒数第二个节点后,链表变为 1 -> 2 -> 3 -> 5。你可以假设,给定的 n 是有效的。额外要求就是,要在一趟扫描中实现,即时间复杂度是 O(n)。这里给你一个提示,可以采用快慢指针的方法。</p>
|
||
<p><strong>【解析】</strong> 定义快慢指针,slow 和 fast 并同时指向 header。然后,让 fast 指针先走 n 步。接着,让二者保持同样的速度,一起往前走。最后,fast 指针先到达终点,并指向了 null。此时,slow 指针的结果就是倒数第 n 个结点。比较简单,我们就不给代码了。</p>
|
||
<h4>19 | 真题案例(四):大厂真题实战演练</h4>
|
||
<p><strong>【问题】</strong> 小明从小就喜欢数学,喜欢在笔记里记录很多表达式。他觉得现在的表达式写法很麻烦,为了提高运算符优先级,不得不添加很多括号。如果不小心漏了一个右括号的话,就差之毫厘,谬之千里了。因此他改用前缀表达式,例如把 <code>(2 + 3) * 4</code>写成<code>* + 2 3 4</code>,这样就能避免使用括号了。这样的表达式虽然书写简单,但计算却不够直观。请你写一个程序帮他计算这些前缀表达式。</p>
|
||
<p><strong>【解析】</strong> 在这个题目中,输入就是前缀表达式,输出就是计算的结果。你可以假设除法为整除,即 “5/3 = 1”。例如,输入字符串为 + 2 3,输出 5;输入字符串为 * + 2 2 3,输出为 12;输入字符串为 * 2 + 2 3,输出为 10。</p>
|
||
<p>假设输入字符串为 * 2 + 2 3,即 2*(2+3)。第一个字符为运算符号 *,它将对两个数字进行乘法。如果后面紧接着的字符不全是数字字符,那就需要暂存下来,先计算后面的算式。一旦后面的计算完成,就需要接着从后往前去继续计算。因为从后往前是一种逆序动作,我们能够很自然地想到可以用栈的数据结构进行存储。代码如下:</p>
|
||
<pre><code>public static void main(String[] args) {
|
||
Stack<Object> stack = new Stack<Object>();
|
||
String s = "* + 2 2 3";
|
||
String attr[] = s.split(" ");
|
||
for (int i = attr.length - 1; i >= 0; i--) {
|
||
if (!(attr[i].equals("+") || attr[i].equals("-") || attr[i].equals("*") || attr[i].equals("/"))) {
|
||
stack.push(Integer.parseInt(attr[i]));
|
||
} else {
|
||
int a = (int) stack.pop();// 出栈
|
||
int b = (int) stack.pop();// 出栈
|
||
int result = Cal(a, b, attr[i]); // 调用函数计算结果值
|
||
stack.push(result); // 结果进栈
|
||
}
|
||
}
|
||
int ans = (int) stack.pop();
|
||
System.out.print(ans);
|
||
}
|
||
public static int Cal(int a, int b, String s) {
|
||
switch (s) {
|
||
case "+":
|
||
return a + b;
|
||
case "-":
|
||
return a - b;
|
||
case "*":
|
||
return a * b;
|
||
case "/":
|
||
return a / b;
|
||
}
|
||
return 0;
|
||
}
|
||
</code></pre>
|
||
<p>以上这些练习题你做得怎么样呢?还能回忆起来每道题是源自哪个算法知识点或哪个课时吗?</p>
|
||
<p>你可以把课后习题和课程中的案例都当作一个小项目,自己动手实践,即使有些题目你还不能写出完整的代码,那也可以尝试写出解题思路,从看不明白到能够理解,再到能联想到用什么数据结构和算法去解决什么样的问题,这是一个循序渐进的过程,切勿着急。</p>
|
||
<p>通过留言可以看出,你们都在认真地学习这门课程,也正因如此,我才愿意付出更多的时间优化这个已经完结的专栏。所以,请你不要犹豫,尽管畅所欲言,在留言区留下你的思考,也欢迎你积极地提问,更欢迎你为专栏提出建议,这样我才能更直接地看到你们的想法和收获。也许你的一条留言,就是下一篇加餐的主题。</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<div style="float: left">
|
||
<a href="/专栏/重学数据结构与算法-完/21 面试中如何建立全局观,快速完成优质的手写代码?.md.html">上一页</a>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
|
||
</div>
|
||
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"70997deedfb33cfa","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
|
||
</body>
|
||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
|
||
<script>
|
||
window.dataLayer = window.dataLayer || [];
|
||
function gtag() {
|
||
dataLayer.push(arguments);
|
||
}
|
||
gtag('js', new Date());
|
||
gtag('config', 'G-NPSEEVD756');
|
||
var path = window.location.pathname
|
||
var cookie = getCookie("lastPath");
|
||
console.log(path)
|
||
if (path.replace("/", "") === "") {
|
||
if (cookie.replace("/", "") !== "") {
|
||
console.log(cookie)
|
||
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
|
||
}
|
||
} else {
|
||
setCookie("lastPath", path)
|
||
}
|
||
function setCookie(cname, cvalue) {
|
||
var d = new Date();
|
||
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
|
||
var expires = "expires=" + d.toGMTString();
|
||
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
|
||
}
|
||
function getCookie(cname) {
|
||
var name = cname + "=";
|
||
var ca = document.cookie.split(';');
|
||
for (var i = 0; i < ca.length; i++) {
|
||
var c = ca[i].trim();
|
||
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
|
||
}
|
||
return "";
|
||
}
|
||
</script>
|
||
</html>
|