-
Notifications
You must be signed in to change notification settings - Fork 0
/
en.search-data.min.993524b68fd60e48caec514a4cfbd9a0c154ab86f4df856e000a21e31c765436.json
1 lines (1 loc) · 208 KB
/
en.search-data.min.993524b68fd60e48caec514a4cfbd9a0c154ab86f4df856e000a21e31c765436.json
1
[{"id":0,"href":"/docs/topic/","title":"Topic","section":"Docs","content":" Ubi loqui # Mentem genus facietque salire tempus bracchia # Lorem markdownum partu paterno Achillem. Habent amne generosi aderant ad pellem nec erat sustinet merces columque haec et, dixit minus nutrit accipiam subibis subdidit. Temeraria servatum agros qui sed fulva facta. Primum ultima, dedit, suo quisque linguae medentes fixo: tum petis.\nRapit vocant si hunc siste adspice # Ora precari Patraeque Neptunia, dixit Danae Cithaeron armaque maxima in nati Coniugis templis fluidove. Effugit usus nec ingreditur agmen ac manus conlato. Nullis vagis nequiquam vultibus aliquos altera suum venis teneas fretum. Armos remotis hoc sine ferrea iuncta quam!\nLocus fuit caecis # Nefas discordemque domino montes numen tum humili nexilibusque exit, Iove. Quae miror esse, scelerisque Melaneus viribus. Miseri laurus. Hoc est proposita me ante aliquid, aura inponere candidioribus quidque accendit bella, sumpta. Intravit quam erat figentem hunc, motus de fontes parvo tempestate.\niscsi_virus = pitch(json_in_on(eupViral), northbridge_services_troubleshooting, personal( firmware_rw.trash_rw_crm.device(interactive_gopher_personal, software, -1), megabit, ergonomicsSoftware(cmyk_usb_panel, mips_whitelist_duplex, cpa))); if (5) { managementNetwork += dma - boolean; kilohertz_token = 2; honeypot_affiliate_ergonomics = fiber; } mouseNorthbridge = byte(nybble_xmp_modem.horse_subnet( analogThroughputService * graphicPoint, drop(daw_bit, dnsIntranet), gateway_ospf), repository.domain_key.mouse(serverData(fileNetwork, trim_duplex_file), cellTapeDirect, token_tooltip_mashup( ripcordingMashup))); module_it = honeypot_driver(client_cold_dvr(593902, ripping_frequency) + coreLog.joystick(componentUdpLink), windows_expansion_touchscreen); bashGigabit.external.reality(2, server_hardware_codec.flops.ebookSampling( ciscNavigationBacklink, table + cleanDriver), indexProtocolIsp); class Solution { public static void main(String[] args) { System.out.println(\u0026#34;Hello, world!\u0026#34;); } } Placabilis coactis nega ingemuit ignoscat nimia non # Frontis turba. Oculi gravis est Delphice; inque praedaque sanguine manu non.\nif (ad_api) { zif += usb.tiffAvatarRate(subnet, digital_rt) + exploitDrive; gigaflops(2 - bluetooth, edi_asp_memory.gopher(queryCursor, laptop), panel_point_firmware); spyware_bash.statePopApplet = express_netbios_digital( insertion_troubleshooting.brouter(recordFolderUs), 65); } recursionCoreRay = -5; if (hub == non) { portBoxVirus = soundWeb(recursive_card(rwTechnologyLeopard), font_radcab, guidCmsScalable + reciprocalMatrixPim); left.bug = screenshot; } else { tooltipOpacity = raw_process_permalink(webcamFontUser, -1); executable_router += tape; } if (tft) { bandwidthWeb *= social_page; } else { regular += 611883; thumbnail /= system_lag_keyboard; } Caesorum illa tu sentit micat vestes papyriferi # Inde aderam facti; Theseus vis de tauri illa peream. Oculos uberaque non regisque vobis cursuque, opus venit quam vulnera. Et maiora necemque, lege modo; gestanda nitidi, vero? Dum ne pectoraque testantur.\nVenasque repulsa Samos qui, exspectatum eram animosque hinc, aut manes, Assyrii. Cupiens auctoribus pariter rubet, profana magni super nocens. Vos ius sibilat inpar turba visae iusto! Sedes ante dum superest extrema.\n"},{"id":1,"href":"/docs/codes/","title":"Codes","section":"Docs","content":" Ubi loqui # Mentem genus facietque salire tempus bracchia # Lorem markdownum partu paterno Achillem. Habent amne generosi aderant ad pellem nec erat sustinet merces columque haec et, dixit minus nutrit accipiam subibis subdidit. Temeraria servatum agros qui sed fulva facta. Primum ultima, dedit, suo quisque linguae medentes fixo: tum petis.\nRapit vocant si hunc siste adspice # Ora precari Patraeque Neptunia, dixit Danae Cithaeron armaque maxima in nati Coniugis templis fluidove. Effugit usus nec ingreditur agmen ac manus conlato. Nullis vagis nequiquam vultibus aliquos altera suum venis teneas fretum. Armos remotis hoc sine ferrea iuncta quam!\nLocus fuit caecis # Nefas discordemque domino montes numen tum humili nexilibusque exit, Iove. Quae miror esse, scelerisque Melaneus viribus. Miseri laurus. Hoc est proposita me ante aliquid, aura inponere candidioribus quidque accendit bella, sumpta. Intravit quam erat figentem hunc, motus de fontes parvo tempestate.\niscsi_virus = pitch(json_in_on(eupViral), northbridge_services_troubleshooting, personal( firmware_rw.trash_rw_crm.device(interactive_gopher_personal, software, -1), megabit, ergonomicsSoftware(cmyk_usb_panel, mips_whitelist_duplex, cpa))); if (5) { managementNetwork += dma - boolean; kilohertz_token = 2; honeypot_affiliate_ergonomics = fiber; } mouseNorthbridge = byte(nybble_xmp_modem.horse_subnet( analogThroughputService * graphicPoint, drop(daw_bit, dnsIntranet), gateway_ospf), repository.domain_key.mouse(serverData(fileNetwork, trim_duplex_file), cellTapeDirect, token_tooltip_mashup( ripcordingMashup))); module_it = honeypot_driver(client_cold_dvr(593902, ripping_frequency) + coreLog.joystick(componentUdpLink), windows_expansion_touchscreen); bashGigabit.external.reality(2, server_hardware_codec.flops.ebookSampling( ciscNavigationBacklink, table + cleanDriver), indexProtocolIsp); class Solution { "},{"id":2,"href":"/docs/templates/","title":"Templates","section":"Docs","content":" Ubi loqui # Mentem genus facietque salire tempus bracchia # Lorem markdownum partu paterno Achillem. Habent amne generosi aderant ad pellem nec erat sustinet merces columque haec et, dixit minus nutrit accipiam subibis subdidit. Temeraria servatum agros qui sed fulva facta. Primum ultima, dedit, suo quisque linguae medentes fixo: tum petis.\nRapit vocant si hunc siste adspice # Ora precari Patraeque Neptunia, dixit Danae Cithaeron armaque maxima in nati Coniugis templis fluidove. Effugit usus nec ingreditur agmen ac manus conlato. Nullis vagis nequiquam vultibus aliquos altera suum venis teneas fretum. Armos remotis hoc sine ferrea iuncta quam!\nLocus fuit caecis # Nefas discordemque domino montes numen tum humili nexilibusque exit, Iove. Quae miror esse, scelerisque Melaneus viribus. Miseri laurus. Hoc est proposita me ante aliquid, aura inponere candidioribus quidque accendit bella, sumpta. Intravit quam erat figentem hunc, motus de fontes parvo tempestate.\niscsi_virus = pitch(json_in_on(eupViral), northbridge_services_troubleshooting, personal( firmware_rw.trash_rw_crm.device(interactive_gopher_personal, software, -1), megabit, ergonomicsSoftware(cmyk_usb_panel, mips_whitelist_duplex, cpa))); if (5) { managementNetwork += dma - boolean; kilohertz_token = 2; honeypot_affiliate_ergonomics = fiber; } mouseNorthbridge = byte(nybble_xmp_modem.horse_subnet( analogThroughputService * graphicPoint, drop(daw_bit, dnsIntranet), gateway_ospf), repository.domain_key.mouse(serverData(fileNetwork, trim_duplex_file), cellTapeDirect, token_tooltip_mashup( ripcordingMashup))); module_it = honeypot_driver(client_cold_dvr(593902, ripping_frequency) + coreLog.joystick(componentUdpLink), windows_expansion_touchscreen); bashGigabit.external.reality(2, server_hardware_codec.flops.ebookSampling( ciscNavigationBacklink, table + cleanDriver), indexProtocolIsp); class Solution { public static void main(String[] args) { System.out.println(\u0026#34;Hello, world!\u0026#34;); } } Placabilis coactis nega ingemuit ignoscat nimia non # Frontis turba. Oculi gravis est Delphice; inque praedaque sanguine manu non.\nif (ad_api) { zif += usb.tiffAvatarRate(subnet, digital_rt) + exploitDrive; gigaflops(2 - bluetooth, edi_asp_memory.gopher(queryCursor, laptop), panel_point_firmware); spyware_bash.statePopApplet = express_netbios_digital( insertion_troubleshooting.brouter(recordFolderUs), 65); } recursionCoreRay = -5; if (hub == non) { portBoxVirus = soundWeb(recursive_card(rwTechnologyLeopard), font_radcab, guidCmsScalable + reciprocalMatrixPim); left.bug = screenshot; } else { tooltipOpacity = raw_process_permalink(webcamFontUser, -1); executable_router += tape; } if (tft) { bandwidthWeb *= social_page; } else { regular += 611883; thumbnail /= system_lag_keyboard; } Caesorum illa tu sentit micat vestes papyriferi # Inde aderam facti; Theseus vis de tauri illa peream. Oculos uberaque non regisque vobis cursuque, opus venit quam vulnera. Et maiora necemque, lege modo; gestanda nitidi, vero? Dum ne pectoraque testantur.\nVenasque repulsa Samos qui, exspectatum eram animosque hinc, aut manes, Assyrii. Cupiens auctoribus pariter rubet, profana magni super nocens. Vos ius sibilat inpar turba visae iusto! Sedes ante dum superest extrema.\n"},{"id":3,"href":"/posts/creating-a-new-theme/","title":"Creating a New Theme","section":"Blog","content":" Introduction # This tutorial will show you how to create a simple theme in Hugo. I assume that you are familiar with HTML, the bash command line, and that you are comfortable using Markdown to format content. I\u0026rsquo;ll explain how Hugo uses templates and how you can organize your templates to create a theme. I won\u0026rsquo;t cover using CSS to style your theme.\nWe\u0026rsquo;ll start with creating a new site with a very basic template. Then we\u0026rsquo;ll add in a few pages and posts. With small variations on that, you will be able to create many different types of web sites.\nIn this tutorial, commands that you enter will start with the \u0026ldquo;$\u0026rdquo; prompt. The output will follow. Lines that start with \u0026ldquo;#\u0026rdquo; are comments that I\u0026rsquo;ve added to explain a point. When I show updates to a file, the \u0026ldquo;:wq\u0026rdquo; on the last line means to save the file.\nHere\u0026rsquo;s an example:\n## this is a comment $ echo this is a command this is a command ## edit the file $ vi foo.md +++ date = \u0026#34;2014-09-28\u0026#34; title = \u0026#34;creating a new theme\u0026#34; +++ bah and humbug :wq ## show it $ cat foo.md +++ date = \u0026#34;2014-09-28\u0026#34; title = \u0026#34;creating a new theme\u0026#34; +++ bah and humbug $ Some Definitions # There are a few concepts that you need to understand before creating a theme.\nSkins # Skins are the files responsible for the look and feel of your site. It’s the CSS that controls colors and fonts, it’s the Javascript that determines actions and reactions. It’s also the rules that Hugo uses to transform your content into the HTML that the site will serve to visitors.\nYou have two ways to create a skin. The simplest way is to create it in the layouts/ directory. If you do, then you don’t have to worry about configuring Hugo to recognize it. The first place that Hugo will look for rules and files is in the layouts/ directory so it will always find the skin.\nYour second choice is to create it in a sub-directory of the themes/ directory. If you do, then you must always tell Hugo where to search for the skin. It’s extra work, though, so why bother with it?\nThe difference between creating a skin in layouts/ and creating it in themes/ is very subtle. A skin in layouts/ can’t be customized without updating the templates and static files that it is built from. A skin created in themes/, on the other hand, can be and that makes it easier for other people to use it.\nThe rest of this tutorial will call a skin created in the themes/ directory a theme.\nNote that you can use this tutorial to create a skin in the layouts/ directory if you wish to. The main difference will be that you won’t need to update the site’s configuration file to use a theme.\nThe Home Page # The home page, or landing page, is the first page that many visitors to a site see. It is the index.html file in the root directory of the web site. Since Hugo writes files to the public/ directory, our home page is public/index.html.\nSite Configuration File # When Hugo runs, it looks for a configuration file that contains settings that override default values for the entire site. The file can use TOML, YAML, or JSON. I prefer to use TOML for my configuration files. If you prefer to use JSON or YAML, you’ll need to translate my examples. You’ll also need to change the name of the file since Hugo uses the extension to determine how to process it.\nHugo translates Markdown files into HTML. By default, Hugo expects to find Markdown files in your content/ directory and template files in your themes/ directory. It will create HTML files in your public/ directory. You can change this by specifying alternate locations in the configuration file.\nContent # Content is stored in text files that contain two sections. The first section is the “front matter,” which is the meta-information on the content. The second section contains Markdown that will be converted to HTML.\nFront Matter # The front matter is information about the content. Like the configuration file, it can be written in TOML, YAML, or JSON. Unlike the configuration file, Hugo doesn’t use the file’s extension to know the format. It looks for markers to signal the type. TOML is surrounded by “+++”, YAML by “---”, and JSON is enclosed in curly braces. I prefer to use TOML, so you’ll need to translate my examples if you prefer YAML or JSON.\nThe information in the front matter is passed into the template before the content is rendered into HTML.\nMarkdown # Content is written in Markdown which makes it easier to create the content. Hugo runs the content through a Markdown engine to create the HTML which will be written to the output file.\nTemplate Files # Hugo uses template files to render content into HTML. Template files are a bridge between the content and presentation. Rules in the template define what content is published, where it\u0026rsquo;s published to, and how it will rendered to the HTML file. The template guides the presentation by specifying the style to use.\nThere are three types of templates: single, list, and partial. Each type takes a bit of content as input and transforms it based on the commands in the template.\nHugo uses its knowledge of the content to find the template file used to render the content. If it can’t find a template that is an exact match for the content, it will shift up a level and search from there. It will continue to do so until it finds a matching template or runs out of templates to try. If it can’t find a template, it will use the default template for the site.\nPlease note that you can use the front matter to influence Hugo’s choice of templates.\nSingle Template # A single template is used to render a single piece of content. For example, an article or post would be a single piece of content and use a single template.\nList Template # A list template renders a group of related content. That could be a summary of recent postings or all articles in a category. List templates can contain multiple groups.\nThe homepage template is a special type of list template. Hugo assumes that the home page of your site will act as the portal for the rest of the content in the site.\nPartial Template # A partial template is a template that can be included in other templates. Partial templates must be called using the “partial” template command. They are very handy for rolling up common behavior. For example, your site may have a banner that all pages use. Instead of copying the text of the banner into every single and list template, you could create a partial with the banner in it. That way if you decide to change the banner, you only have to change the partial template.\nCreate a New Site # Let\u0026rsquo;s use Hugo to create a new web site. I\u0026rsquo;m a Mac user, so I\u0026rsquo;ll create mine in my home directory, in the Sites folder. If you\u0026rsquo;re using Linux, you might have to create the folder first.\nThe \u0026ldquo;new site\u0026rdquo; command will create a skeleton of a site. It will give you the basic directory structure and a useable configuration file.\n$ hugo new site ~/Sites/zafta $ cd ~/Sites/zafta $ ls -l total 8 drwxr-xr-x 7 quoha staff 238 Sep 29 16:49 . drwxr-xr-x 3 quoha staff 102 Sep 29 16:49 .. drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 archetypes -rw-r--r-- 1 quoha staff 82 Sep 29 16:49 config.toml drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 content drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 layouts drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 static $ Take a look in the content/ directory to confirm that it is empty.\nThe other directories (archetypes/, layouts/, and static/) are used when customizing a theme. That\u0026rsquo;s a topic for a different tutorial, so please ignore them for now.\nGenerate the HTML For the New Site # Running the hugo command with no options will read all the available content and generate the HTML files. It will also copy all static files (that\u0026rsquo;s everything that\u0026rsquo;s not content). Since we have an empty site, it won\u0026rsquo;t do much, but it will do it very quickly.\n$ hugo --verbose INFO: 2014/09/29 Using config file: config.toml INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ WARN: 2014/09/29 Unable to locate layout: [index.html _default/list.html _default/single.html] WARN: 2014/09/29 Unable to locate layout: [404.html] 0 draft content 0 future content 0 pages created 0 tags created 0 categories created in 2 ms $ The \u0026ldquo;--verbose\u0026rdquo; flag gives extra information that will be helpful when we build the template. Every line of the output that starts with \u0026ldquo;INFO:\u0026rdquo; or \u0026ldquo;WARN:\u0026rdquo; is present because we used that flag. The lines that start with \u0026ldquo;WARN:\u0026rdquo; are warning messages. We\u0026rsquo;ll go over them later.\nWe can verify that the command worked by looking at the directory again.\n$ ls -l total 8 drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 archetypes -rw-r--r-- 1 quoha staff 82 Sep 29 16:49 config.toml drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 content drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 layouts drwxr-xr-x 4 quoha staff 136 Sep 29 17:02 public drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 static $ See that new public/ directory? Hugo placed all generated content there. When you\u0026rsquo;re ready to publish your web site, that\u0026rsquo;s the place to start. For now, though, let\u0026rsquo;s just confirm that we have what we\u0026rsquo;d expect from a site with no content.\n$ ls -l public total 16 -rw-r--r-- 1 quoha staff 416 Sep 29 17:02 index.xml -rw-r--r-- 1 quoha staff 262 Sep 29 17:02 sitemap.xml $ Hugo created two XML files, which is standard, but there are no HTML files.\nTest the New Site # Verify that you can run the built-in web server. It will dramatically shorten your development cycle if you do. Start it by running the \u0026ldquo;server\u0026rdquo; command. If it is successful, you will see output similar to the following:\n$ hugo server --verbose INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ WARN: 2014/09/29 Unable to locate layout: [index.html _default/list.html _default/single.html] WARN: 2014/09/29 Unable to locate layout: [404.html] 0 draft content 0 future content 0 pages created 0 tags created 0 categories created in 2 ms Serving pages from /Users/quoha/Sites/zafta/public Web Server is available at http://localhost:1313 Press Ctrl+C to stop Connect to the listed URL (it\u0026rsquo;s on the line that starts with \u0026ldquo;Web Server\u0026rdquo;). If everything is working correctly, you should get a page that shows the following:\nindex.xml sitemap.xml That\u0026rsquo;s a listing of your public/ directory. Hugo didn\u0026rsquo;t create a home page because our site has no content. When there\u0026rsquo;s no index.html file in a directory, the server lists the files in the directory, which is what you should see in your browser.\nLet’s go back and look at those warnings again.\nWARN: 2014/09/29 Unable to locate layout: [index.html _default/list.html _default/single.html] WARN: 2014/09/29 Unable to locate layout: [404.html] That second warning is easier to explain. We haven’t created a template to be used to generate “page not found errors.” The 404 message is a topic for a separate tutorial.\nNow for the first warning. It is for the home page. You can tell because the first layout that it looked for was “index.html.” That’s only used by the home page.\nI like that the verbose flag causes Hugo to list the files that it\u0026rsquo;s searching for. For the home page, they are index.html, _default/list.html, and _default/single.html. There are some rules that we\u0026rsquo;ll cover later that explain the names and paths. For now, just remember that Hugo couldn\u0026rsquo;t find a template for the home page and it told you so.\nAt this point, you\u0026rsquo;ve got a working installation and site that we can build upon. All that’s left is to add some content and a theme to display it.\nCreate a New Theme # Hugo doesn\u0026rsquo;t ship with a default theme. There are a few available (I counted a dozen when I first installed Hugo) and Hugo comes with a command to create new themes.\nWe\u0026rsquo;re going to create a new theme called \u0026ldquo;zafta.\u0026rdquo; Since the goal of this tutorial is to show you how to fill out the files to pull in your content, the theme will not contain any CSS. In other words, ugly but functional.\nAll themes have opinions on content and layout. For example, Zafta uses \u0026ldquo;post\u0026rdquo; over \u0026ldquo;blog\u0026rdquo;. Strong opinions make for simpler templates but differing opinions make it tougher to use themes. When you build a theme, consider using the terms that other themes do.\nCreate a Skeleton # Use the hugo \u0026ldquo;new\u0026rdquo; command to create the skeleton of a theme. This creates the directory structure and places empty files for you to fill out.\n$ hugo new theme zafta $ ls -l total 8 drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 archetypes -rw-r--r-- 1 quoha staff 82 Sep 29 16:49 config.toml drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 content drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 layouts drwxr-xr-x 4 quoha staff 136 Sep 29 17:02 public drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 static drwxr-xr-x 3 quoha staff 102 Sep 29 17:31 themes $ find themes -type f | xargs ls -l -rw-r--r-- 1 quoha staff 1081 Sep 29 17:31 themes/zafta/LICENSE.md -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/archetypes/default.md -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/_default/list.html -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/_default/single.html -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/index.html -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/partials/footer.html -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/partials/header.html -rw-r--r-- 1 quoha staff 93 Sep 29 17:31 themes/zafta/theme.toml $ The skeleton includes templates (the files ending in .html), license file, a description of your theme (the theme.toml file), and an empty archetype.\nPlease take a minute to fill out the theme.toml and LICENSE.md files. They\u0026rsquo;re optional, but if you\u0026rsquo;re going to be distributing your theme, it tells the world who to praise (or blame). It\u0026rsquo;s also nice to declare the license so that people will know how they can use the theme.\n$ vi themes/zafta/theme.toml author = \u0026#34;michael d henderson\u0026#34; description = \u0026#34;a minimal working template\u0026#34; license = \u0026#34;MIT\u0026#34; name = \u0026#34;zafta\u0026#34; source_repo = \u0026#34;\u0026#34; tags = [\u0026#34;tags\u0026#34;, \u0026#34;categories\u0026#34;] :wq ## also edit themes/zafta/LICENSE.md and change ## the bit that says \u0026#34;YOUR_NAME_HERE\u0026#34; Note that the the skeleton\u0026rsquo;s template files are empty. Don\u0026rsquo;t worry, we\u0026rsquo;ll be changing that shortly.\n$ find themes/zafta -name \u0026#39;*.html\u0026#39; | xargs ls -l -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/_default/list.html -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/_default/single.html -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/index.html -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/partials/footer.html -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/partials/header.html $ Update the Configuration File to Use the Theme # Now that we\u0026rsquo;ve got a theme to work with, it\u0026rsquo;s a good idea to add the theme name to the configuration file. This is optional, because you can always add \u0026ldquo;-t zafta\u0026rdquo; on all your commands. I like to put it the configuration file because I like shorter command lines. If you don\u0026rsquo;t put it in the configuration file or specify it on the command line, you won\u0026rsquo;t use the template that you\u0026rsquo;re expecting to.\nEdit the file to add the theme, add a title for the site, and specify that all of our content will use the TOML format.\n$ vi config.toml theme = \u0026#34;zafta\u0026#34; baseurl = \u0026#34;\u0026#34; languageCode = \u0026#34;en-us\u0026#34; title = \u0026#34;zafta - totally refreshing\u0026#34; MetaDataFormat = \u0026#34;toml\u0026#34; :wq $ Generate the Site # Now that we have an empty theme, let\u0026rsquo;s generate the site again.\n$ hugo --verbose INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] 0 draft content 0 future content 0 pages created 0 tags created 0 categories created in 2 ms $ Did you notice that the output is different? The warning message for the home page has disappeared and we have an additional information line saying that Hugo is syncing from the theme\u0026rsquo;s directory.\nLet\u0026rsquo;s check the public/ directory to see what Hugo\u0026rsquo;s created.\n$ ls -l public total 16 drwxr-xr-x 2 quoha staff 68 Sep 29 17:56 css -rw-r--r-- 1 quoha staff 0 Sep 29 17:56 index.html -rw-r--r-- 1 quoha staff 407 Sep 29 17:56 index.xml drwxr-xr-x 2 quoha staff 68 Sep 29 17:56 js -rw-r--r-- 1 quoha staff 243 Sep 29 17:56 sitemap.xml $ Notice four things:\nHugo created a home page. This is the file public/index.html. Hugo created a css/ directory. Hugo created a js/ directory. Hugo claimed that it created 0 pages. It created a file and copied over static files, but didn\u0026rsquo;t create any pages. That\u0026rsquo;s because it considers a \u0026ldquo;page\u0026rdquo; to be a file created directly from a content file. It doesn\u0026rsquo;t count things like the index.html files that it creates automatically. The Home Page # Hugo supports many different types of templates. The home page is special because it gets its own type of template and its own template file. The file, layouts/index.html, is used to generate the HTML for the home page. The Hugo documentation says that this is the only required template, but that depends. Hugo\u0026rsquo;s warning message shows that it looks for three different templates:\nWARN: 2014/09/29 Unable to locate layout: [index.html _default/list.html _default/single.html] If it can\u0026rsquo;t find any of these, it completely skips creating the home page. We noticed that when we built the site without having a theme installed.\nWhen Hugo created our theme, it created an empty home page template. Now, when we build the site, Hugo finds the template and uses it to generate the HTML for the home page. Since the template file is empty, the HTML file is empty, too. If the template had any rules in it, then Hugo would have used them to generate the home page.\n$ find . -name index.html | xargs ls -l -rw-r--r-- 1 quoha staff 0 Sep 29 20:21 ./public/index.html -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 ./themes/zafta/layouts/index.html $ The Magic of Static # Hugo does two things when generating the site. It uses templates to transform content into HTML and it copies static files into the site. Unlike content, static files are not transformed. They are copied exactly as they are.\nHugo assumes that your site will use both CSS and JavaScript, so it creates directories in your theme to hold them. Remember opinions? Well, Hugo\u0026rsquo;s opinion is that you\u0026rsquo;ll store your CSS in a directory named css/ and your JavaScript in a directory named js/. If you don\u0026rsquo;t like that, you can change the directory names in your theme directory or even delete them completely. Hugo\u0026rsquo;s nice enough to offer its opinion, then behave nicely if you disagree.\n$ find themes/zafta -type d | xargs ls -ld drwxr-xr-x 7 quoha staff 238 Sep 29 17:38 themes/zafta drwxr-xr-x 3 quoha staff 102 Sep 29 17:31 themes/zafta/archetypes drwxr-xr-x 5 quoha staff 170 Sep 29 17:31 themes/zafta/layouts drwxr-xr-x 4 quoha staff 136 Sep 29 17:31 themes/zafta/layouts/_default drwxr-xr-x 4 quoha staff 136 Sep 29 17:31 themes/zafta/layouts/partials drwxr-xr-x 4 quoha staff 136 Sep 29 17:31 themes/zafta/static drwxr-xr-x 2 quoha staff 68 Sep 29 17:31 themes/zafta/static/css drwxr-xr-x 2 quoha staff 68 Sep 29 17:31 themes/zafta/static/js $ The Theme Development Cycle # When you\u0026rsquo;re working on a theme, you will make changes in the theme\u0026rsquo;s directory, rebuild the site, and check your changes in the browser. Hugo makes this very easy:\nPurge the public/ directory. Run the built in web server in watch mode. Open your site in a browser. Update the theme. Glance at your browser window to see changes. Return to step 4. I’ll throw in one more opinion: never work on a theme on a live site. Always work on a copy of your site. Make changes to your theme, test them, then copy them up to your site. For added safety, use a tool like Git to keep a revision history of your content and your theme. Believe me when I say that it is too easy to lose both your mind and your changes.\nCheck the main Hugo site for information on using Git with Hugo.\nPurge the public/ Directory # When generating the site, Hugo will create new files and update existing ones in the public/ directory. It will not delete files that are no longer used. For example, files that were created in the wrong directory or with the wrong title will remain. If you leave them, you might get confused by them later. I recommend cleaning out your site prior to generating it.\nNote: If you\u0026rsquo;re building on an SSD, you should ignore this. Churning on a SSD can be costly.\nHugo\u0026rsquo;s Watch Option # Hugo\u0026rsquo;s \u0026ldquo;--watch\u0026rdquo; option will monitor the content/ and your theme directories for changes and rebuild the site automatically.\nLive Reload # Hugo\u0026rsquo;s built in web server supports live reload. As pages are saved on the server, the browser is told to refresh the page. Usually, this happens faster than you can say, \u0026ldquo;Wow, that\u0026rsquo;s totally amazing.\u0026rdquo;\nDevelopment Commands # Use the following commands as the basis for your workflow.\n## purge old files. hugo will recreate the public directory. ## $ rm -rf public ## ## run hugo in watch mode ## $ hugo server --watch --verbose Here\u0026rsquo;s sample output showing Hugo detecting a change to the template for the home page. Once generated, the web browser automatically reloaded the page. I\u0026rsquo;ve said this before, it\u0026rsquo;s amazing.\n$ rm -rf public $ hugo server --watch --verbose INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] 0 draft content 0 future content 0 pages created 0 tags created 0 categories created in 2 ms Watching for changes in /Users/quoha/Sites/zafta/content Serving pages from /Users/quoha/Sites/zafta/public Web Server is available at http://localhost:1313 Press Ctrl+C to stop INFO: 2014/09/29 File System Event: [\u0026#34;/Users/quoha/Sites/zafta/themes/zafta/layouts/index.html\u0026#34;: MODIFY|ATTRIB] Change detected, rebuilding site WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] 0 draft content 0 future content 0 pages created 0 tags created 0 categories created in 1 ms Update the Home Page Template # The home page is one of a few special pages that Hugo creates automatically. As mentioned earlier, it looks for one of three files in the theme\u0026rsquo;s layout/ directory:\nindex.html _default/list.html _default/single.html We could update one of the default templates, but a good design decision is to update the most specific template available. That\u0026rsquo;s not a hard and fast rule (in fact, we\u0026rsquo;ll break it a few times in this tutorial), but it is a good generalization.\nMake a Static Home Page # Right now, that page is empty because we don\u0026rsquo;t have any content and we don\u0026rsquo;t have any logic in the template. Let\u0026rsquo;s change that by adding some text to the template.\n$ vi themes/zafta/layouts/index.html \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;hugo says hello!\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; :wq $ Build the web site and then verify the results.\n$ hugo --verbose INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] 0 draft content 0 future content 0 pages created 0 tags created 0 categories created in 2 ms $ find public -type f -name \u0026#39;*.html\u0026#39; | xargs ls -l -rw-r--r-- 1 quoha staff 78 Sep 29 21:26 public/index.html $ cat public/index.html \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;hugo says hello!\u0026lt;/p\u0026gt; \u0026lt;/html\u0026gt; Live Reload # Note: If you\u0026rsquo;re running the server with the --watch option, you\u0026rsquo;ll see different content in the file:\n$ cat public/index.html \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;hugo says hello!\u0026lt;/p\u0026gt; \u0026lt;script\u0026gt;document.write(\u0026#39;\u0026lt;script src=\u0026#34;http://\u0026#39; + (location.host || \u0026#39;localhost\u0026#39;).split(\u0026#39;:\u0026#39;)[0] + \u0026#39;:1313/livereload.js?mindelay=10\u0026#34;\u0026gt;\u0026lt;/\u0026#39; + \u0026#39;script\u0026gt;\u0026#39;)\u0026lt;/script\u0026gt;\u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; When you use --watch, the Live Reload script is added by Hugo. Look for live reload in the documentation to see what it does and how to disable it.\nBuild a \u0026ldquo;Dynamic\u0026rdquo; Home Page # \u0026ldquo;Dynamic home page?\u0026rdquo; Hugo\u0026rsquo;s a static web site generator, so this seems an odd thing to say. I mean let\u0026rsquo;s have the home page automatically reflect the content in the site every time Hugo builds it. We\u0026rsquo;ll use iteration in the template to do that.\nCreate New Posts # Now that we have the home page generating static content, let\u0026rsquo;s add some content to the site. We\u0026rsquo;ll display these posts as a list on the home page and on their own page, too.\nHugo has a command to generate a skeleton post, just like it does for sites and themes.\n$ hugo --verbose new post/first.md INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml INFO: 2014/09/29 attempting to create post/first.md of post INFO: 2014/09/29 curpath: /Users/quoha/Sites/zafta/themes/zafta/archetypes/default.md ERROR: 2014/09/29 Unable to Cast \u0026lt;nil\u0026gt; to map[string]interface{} $ That wasn\u0026rsquo;t very nice, was it?\nThe \u0026ldquo;new\u0026rdquo; command uses an archetype to create the post file. Hugo created an empty default archetype file, but that causes an error when there\u0026rsquo;s a theme. For me, the workaround was to create an archetypes file specifically for the post type.\n$ vi themes/zafta/archetypes/post.md +++ Description = \u0026#34;\u0026#34; Tags = [] Categories = [] +++ :wq $ find themes/zafta/archetypes -type f | xargs ls -l -rw-r--r-- 1 quoha staff 0 Sep 29 21:53 themes/zafta/archetypes/default.md -rw-r--r-- 1 quoha staff 51 Sep 29 21:54 themes/zafta/archetypes/post.md $ hugo --verbose new post/first.md INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml INFO: 2014/09/29 attempting to create post/first.md of post INFO: 2014/09/29 curpath: /Users/quoha/Sites/zafta/themes/zafta/archetypes/post.md INFO: 2014/09/29 creating /Users/quoha/Sites/zafta/content/post/first.md /Users/quoha/Sites/zafta/content/post/first.md created $ hugo --verbose new post/second.md INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml INFO: 2014/09/29 attempting to create post/second.md of post INFO: 2014/09/29 curpath: /Users/quoha/Sites/zafta/themes/zafta/archetypes/post.md INFO: 2014/09/29 creating /Users/quoha/Sites/zafta/content/post/second.md /Users/quoha/Sites/zafta/content/post/second.md created $ ls -l content/post total 16 -rw-r--r-- 1 quoha staff 104 Sep 29 21:54 first.md -rw-r--r-- 1 quoha staff 105 Sep 29 21:57 second.md $ cat content/post/first.md +++ Categories = [] Description = \u0026#34;\u0026#34; Tags = [] date = \u0026#34;2014-09-29T21:54:53-05:00\u0026#34; title = \u0026#34;first\u0026#34; +++ my first post $ cat content/post/second.md +++ Categories = [] Description = \u0026#34;\u0026#34; Tags = [] date = \u0026#34;2014-09-29T21:57:09-05:00\u0026#34; title = \u0026#34;second\u0026#34; +++ my second post $ Build the web site and then verify the results.\n$ rm -rf public $ hugo --verbose INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ INFO: 2014/09/29 found taxonomies: map[string]string{\u0026#34;category\u0026#34;:\u0026#34;categories\u0026#34;, \u0026#34;tag\u0026#34;:\u0026#34;tags\u0026#34;} WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] 0 draft content 0 future content 2 pages created 0 tags created 0 categories created in 4 ms $ The output says that it created 2 pages. Those are our new posts:\n$ find public -type f -name \u0026#39;*.html\u0026#39; | xargs ls -l -rw-r--r-- 1 quoha staff 78 Sep 29 22:13 public/index.html -rw-r--r-- 1 quoha staff 0 Sep 29 22:13 public/post/first/index.html -rw-r--r-- 1 quoha staff 0 Sep 29 22:13 public/post/index.html -rw-r--r-- 1 quoha staff 0 Sep 29 22:13 public/post/second/index.html $ The new files are empty because because the templates used to generate the content are empty. The homepage doesn\u0026rsquo;t show the new content, either. We have to update the templates to add the posts.\nList and Single Templates # In Hugo, we have three major kinds of templates. There\u0026rsquo;s the home page template that we updated previously. It is used only by the home page. We also have \u0026ldquo;single\u0026rdquo; templates which are used to generate output for a single content file. We also have \u0026ldquo;list\u0026rdquo; templates that are used to group multiple pieces of content before generating output.\nGenerally speaking, list templates are named \u0026ldquo;list.html\u0026rdquo; and single templates are named \u0026ldquo;single.html.\u0026rdquo;\nThere are three other types of templates: partials, content views, and terms. We will not go into much detail on these.\nAdd Content to the Homepage # The home page will contain a list of posts. Let\u0026rsquo;s update its template to add the posts that we just created. The logic in the template will run every time we build the site.\n$ vi themes/zafta/layouts/index.html \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;body\u0026gt; {{ range first 10 .Data.Pages }} \u0026lt;h1\u0026gt;{{ .Title }}\u0026lt;/h1\u0026gt; {{ end }} \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; :wq $ Hugo uses the Go template engine. That engine scans the template files for commands which are enclosed between \u0026ldquo;{{\u0026rdquo; and \u0026ldquo;}}\u0026rdquo;. In our template, the commands are:\nrange .Title end The \u0026ldquo;range\u0026rdquo; command is an iterator. We\u0026rsquo;re going to use it to go through the first ten pages. Every HTML file that Hugo creates is treated as a page, so looping through the list of pages will look at every file that will be created.\nThe \u0026ldquo;.Title\u0026rdquo; command prints the value of the \u0026ldquo;title\u0026rdquo; variable. Hugo pulls it from the front matter in the Markdown file.\nThe \u0026ldquo;end\u0026rdquo; command signals the end of the range iterator. The engine loops back to the top of the iteration when it finds \u0026ldquo;end.\u0026rdquo; Everything between the \u0026ldquo;range\u0026rdquo; and \u0026ldquo;end\u0026rdquo; is evaluated every time the engine goes through the iteration. In this file, that would cause the title from the first ten pages to be output as heading level one.\nIt\u0026rsquo;s helpful to remember that some variables, like .Data, are created before any output files. Hugo loads every content file into the variable and then gives the template a chance to process before creating the HTML files.\nBuild the web site and then verify the results.\n$ rm -rf public $ hugo --verbose INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ INFO: 2014/09/29 found taxonomies: map[string]string{\u0026#34;tag\u0026#34;:\u0026#34;tags\u0026#34;, \u0026#34;category\u0026#34;:\u0026#34;categories\u0026#34;} WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] 0 draft content 0 future content 2 pages created 0 tags created 0 categories created in 4 ms $ find public -type f -name \u0026#39;*.html\u0026#39; | xargs ls -l -rw-r--r-- 1 quoha staff 94 Sep 29 22:23 public/index.html -rw-r--r-- 1 quoha staff 0 Sep 29 22:23 public/post/first/index.html -rw-r--r-- 1 quoha staff 0 Sep 29 22:23 public/post/index.html -rw-r--r-- 1 quoha staff 0 Sep 29 22:23 public/post/second/index.html $ cat public/index.html \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;body\u0026gt; \u0026lt;h1\u0026gt;second\u0026lt;/h1\u0026gt; \u0026lt;h1\u0026gt;first\u0026lt;/h1\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; $ Congratulations, the home page shows the title of the two posts. The posts themselves are still empty, but let\u0026rsquo;s take a moment to appreciate what we\u0026rsquo;ve done. Your template now generates output dynamically. Believe it or not, by inserting the range command inside of those curly braces, you\u0026rsquo;ve learned everything you need to know to build a theme. All that\u0026rsquo;s really left is understanding which template will be used to generate each content file and becoming familiar with the commands for the template engine.\nAnd, if that were entirely true, this tutorial would be much shorter. There are a few things to know that will make creating a new template much easier. Don\u0026rsquo;t worry, though, that\u0026rsquo;s all to come.\nAdd Content to the Posts # We\u0026rsquo;re working with posts, which are in the content/post/ directory. That means that their section is \u0026ldquo;post\u0026rdquo; (and if we don\u0026rsquo;t do something weird, their type is also \u0026ldquo;post\u0026rdquo;).\nHugo uses the section and type to find the template file for every piece of content. Hugo will first look for a template file that matches the section or type name. If it can\u0026rsquo;t find one, then it will look in the _default/ directory. There are some twists that we\u0026rsquo;ll cover when we get to categories and tags, but for now we can assume that Hugo will try post/single.html, then _default/single.html.\nNow that we know the search rule, let\u0026rsquo;s see what we actually have available:\n$ find themes/zafta -name single.html | xargs ls -l -rw-r--r-- 1 quoha staff 132 Sep 29 17:31 themes/zafta/layouts/_default/single.html We could create a new template, post/single.html, or change the default. Since we don\u0026rsquo;t know of any other content types, let\u0026rsquo;s start with updating the default.\nRemember, any content that we haven\u0026rsquo;t created a template for will end up using this template. That can be good or bad. Bad because I know that we\u0026rsquo;re going to be adding different types of content and we\u0026rsquo;re going to end up undoing some of the changes we\u0026rsquo;ve made. It\u0026rsquo;s good because we\u0026rsquo;ll be able to see immediate results. It\u0026rsquo;s also good to start here because we can start to build the basic layout for the site. As we add more content types, we\u0026rsquo;ll refactor this file and move logic around. Hugo makes that fairly painless, so we\u0026rsquo;ll accept the cost and proceed.\nPlease see the Hugo documentation on template rendering for all the details on determining which template to use. And, as the docs mention, if you\u0026rsquo;re building a single page application (SPA) web site, you can delete all of the other templates and work with just the default single page. That\u0026rsquo;s a refreshing amount of joy right there.\nUpdate the Template File # $ vi themes/zafta/layouts/_default/single.html \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;title\u0026gt;{{ .Title }}\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;h1\u0026gt;{{ .Title }}\u0026lt;/h1\u0026gt; {{ .Content }} \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; :wq $ Build the web site and verify the results.\n$ rm -rf public $ hugo --verbose INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ INFO: 2014/09/29 found taxonomies: map[string]string{\u0026#34;tag\u0026#34;:\u0026#34;tags\u0026#34;, \u0026#34;category\u0026#34;:\u0026#34;categories\u0026#34;} WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] 0 draft content 0 future content 2 pages created 0 tags created 0 categories created in 4 ms $ find public -type f -name \u0026#39;*.html\u0026#39; | xargs ls -l -rw-r--r-- 1 quoha staff 94 Sep 29 22:40 public/index.html -rw-r--r-- 1 quoha staff 125 Sep 29 22:40 public/post/first/index.html -rw-r--r-- 1 quoha staff 0 Sep 29 22:40 public/post/index.html -rw-r--r-- 1 quoha staff 128 Sep 29 22:40 public/post/second/index.html $ cat public/post/first/index.html \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;title\u0026gt;first\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;h1\u0026gt;first\u0026lt;/h1\u0026gt; \u0026lt;p\u0026gt;my first post\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; $ cat public/post/second/index.html \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;title\u0026gt;second\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;h1\u0026gt;second\u0026lt;/h1\u0026gt; \u0026lt;p\u0026gt;my second post\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; $ Notice that the posts now have content. You can go to localhost:1313/post/first to verify.\nLinking to Content # The posts are on the home page. Let\u0026rsquo;s add a link from there to the post. Since this is the home page, we\u0026rsquo;ll update its template.\n$ vi themes/zafta/layouts/index.html \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;body\u0026gt; {{ range first 10 .Data.Pages }} \u0026lt;h1\u0026gt;\u0026lt;a href=\u0026#34;{{ .Permalink }}\u0026#34;\u0026gt;{{ .Title }}\u0026lt;/a\u0026gt;\u0026lt;/h1\u0026gt; {{ end }} \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; Build the web site and verify the results.\n$ rm -rf public $ hugo --verbose INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ INFO: 2014/09/29 found taxonomies: map[string]string{\u0026#34;tag\u0026#34;:\u0026#34;tags\u0026#34;, \u0026#34;category\u0026#34;:\u0026#34;categories\u0026#34;} WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] 0 draft content 0 future content 2 pages created 0 tags created 0 categories created in 4 ms $ find public -type f -name \u0026#39;*.html\u0026#39; | xargs ls -l -rw-r--r-- 1 quoha staff 149 Sep 29 22:44 public/index.html -rw-r--r-- 1 quoha staff 125 Sep 29 22:44 public/post/first/index.html -rw-r--r-- 1 quoha staff 0 Sep 29 22:44 public/post/index.html -rw-r--r-- 1 quoha staff 128 Sep 29 22:44 public/post/second/index.html $ cat public/index.html \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;body\u0026gt; \u0026lt;h1\u0026gt;\u0026lt;a href=\u0026#34;/post/second/\u0026#34;\u0026gt;second\u0026lt;/a\u0026gt;\u0026lt;/h1\u0026gt; \u0026lt;h1\u0026gt;\u0026lt;a href=\u0026#34;/post/first/\u0026#34;\u0026gt;first\u0026lt;/a\u0026gt;\u0026lt;/h1\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; $ Create a Post Listing # We have the posts displaying on the home page and on their own page. We also have a file public/post/index.html that is empty. Let\u0026rsquo;s make it show a list of all posts (not just the first ten).\nWe need to decide which template to update. This will be a listing, so it should be a list template. Let\u0026rsquo;s take a quick look and see which list templates are available.\n$ find themes/zafta -name list.html | xargs ls -l -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/_default/list.html As with the single post, we have to decide to update _default/list.html or create post/list.html. We still don\u0026rsquo;t have multiple content types, so let\u0026rsquo;s stay consistent and update the default list template.\nCreating Top Level Pages # Let\u0026rsquo;s add an \u0026ldquo;about\u0026rdquo; page and display it at the top level (as opposed to a sub-level like we did with posts).\nThe default in Hugo is to use the directory structure of the content/ directory to guide the location of the generated html in the public/ directory. Let\u0026rsquo;s verify that by creating an \u0026ldquo;about\u0026rdquo; page at the top level:\n$ vi content/about.md +++ title = \u0026#34;about\u0026#34; description = \u0026#34;about this site\u0026#34; date = \u0026#34;2014-09-27\u0026#34; slug = \u0026#34;about time\u0026#34; +++ ## about us i\u0026#39;m speechless :wq Generate the web site and verify the results.\n$ find public -name \u0026#39;*.html\u0026#39; | xargs ls -l -rw-rw-r-- 1 mdhender staff 334 Sep 27 15:08 public/about-time/index.html -rw-rw-r-- 1 mdhender staff 527 Sep 27 15:08 public/index.html -rw-rw-r-- 1 mdhender staff 358 Sep 27 15:08 public/post/first-post/index.html -rw-rw-r-- 1 mdhender staff 0 Sep 27 15:08 public/post/index.html -rw-rw-r-- 1 mdhender staff 342 Sep 27 15:08 public/post/second-post/index.html Notice that the page wasn\u0026rsquo;t created at the top level. It was created in a sub-directory named \u0026lsquo;about-time/\u0026rsquo;. That name came from our slug. Hugo will use the slug to name the generated content. It\u0026rsquo;s a reasonable default, by the way, but we can learn a few things by fighting it for this file.\nOne other thing. Take a look at the home page.\n$ cat public/index.html \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;body\u0026gt; \u0026lt;h1\u0026gt;\u0026lt;a href=\u0026#34;http://localhost:1313/post/theme/\u0026#34;\u0026gt;creating a new theme\u0026lt;/a\u0026gt;\u0026lt;/h1\u0026gt; \u0026lt;h1\u0026gt;\u0026lt;a href=\u0026#34;http://localhost:1313/about-time/\u0026#34;\u0026gt;about\u0026lt;/a\u0026gt;\u0026lt;/h1\u0026gt; \u0026lt;h1\u0026gt;\u0026lt;a href=\u0026#34;http://localhost:1313/post/second-post/\u0026#34;\u0026gt;second\u0026lt;/a\u0026gt;\u0026lt;/h1\u0026gt; \u0026lt;h1\u0026gt;\u0026lt;a href=\u0026#34;http://localhost:1313/post/first-post/\u0026#34;\u0026gt;first\u0026lt;/a\u0026gt;\u0026lt;/h1\u0026gt; \u0026lt;script\u0026gt;document.write(\u0026#39;\u0026lt;script src=\u0026#34;http://\u0026#39; + (location.host || \u0026#39;localhost\u0026#39;).split(\u0026#39;:\u0026#39;)[0] + \u0026#39;:1313/livereload.js?mindelay=10\u0026#34;\u0026gt;\u0026lt;/\u0026#39; + \u0026#39;script\u0026gt;\u0026#39;)\u0026lt;/script\u0026gt;\u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; Notice that the \u0026ldquo;about\u0026rdquo; link is listed with the posts? That\u0026rsquo;s not desirable, so let\u0026rsquo;s change that first.\n$ vi themes/zafta/layouts/index.html \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;body\u0026gt; \u0026lt;h1\u0026gt;posts\u0026lt;/h1\u0026gt; {{ range first 10 .Data.Pages }} {{ if eq .Type \u0026#34;post\u0026#34;}} \u0026lt;h2\u0026gt;\u0026lt;a href=\u0026#34;{{ .Permalink }}\u0026#34;\u0026gt;{{ .Title }}\u0026lt;/a\u0026gt;\u0026lt;/h2\u0026gt; {{ end }} {{ end }} \u0026lt;h1\u0026gt;pages\u0026lt;/h1\u0026gt; {{ range .Data.Pages }} {{ if eq .Type \u0026#34;page\u0026#34; }} \u0026lt;h2\u0026gt;\u0026lt;a href=\u0026#34;{{ .Permalink }}\u0026#34;\u0026gt;{{ .Title }}\u0026lt;/a\u0026gt;\u0026lt;/h2\u0026gt; {{ end }} {{ end }} \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; :wq Generate the web site and verify the results. The home page has two sections, posts and pages, and each section has the right set of headings and links in it.\nBut, that about page still renders to about-time/index.html.\n$ find public -name \u0026#39;*.html\u0026#39; | xargs ls -l -rw-rw-r-- 1 mdhender staff 334 Sep 27 15:33 public/about-time/index.html -rw-rw-r-- 1 mdhender staff 645 Sep 27 15:33 public/index.html -rw-rw-r-- 1 mdhender staff 358 Sep 27 15:33 public/post/first-post/index.html -rw-rw-r-- 1 mdhender staff 0 Sep 27 15:33 public/post/index.html -rw-rw-r-- 1 mdhender staff 342 Sep 27 15:33 public/post/second-post/index.html Knowing that hugo is using the slug to generate the file name, the simplest solution is to change the slug. Let\u0026rsquo;s do it the hard way and change the permalink in the configuration file.\n$ vi config.toml [permalinks] page = \u0026#34;/:title/\u0026#34; about = \u0026#34;/:filename/\u0026#34; Generate the web site and verify that this didn\u0026rsquo;t work. Hugo lets \u0026ldquo;slug\u0026rdquo; or \u0026ldquo;URL\u0026rdquo; override the permalinks setting in the configuration file. Go ahead and comment out the slug in content/about.md, then generate the web site to get it to be created in the right place.\nSharing Templates # If you\u0026rsquo;ve been following along, you probably noticed that posts have titles in the browser and the home page doesn\u0026rsquo;t. That\u0026rsquo;s because we didn\u0026rsquo;t put the title in the home page\u0026rsquo;s template (layouts/index.html). That\u0026rsquo;s an easy thing to do, but let\u0026rsquo;s look at a different option.\nWe can put the common bits into a shared template that\u0026rsquo;s stored in the themes/zafta/layouts/partials/ directory.\nCreate the Header and Footer Partials # In Hugo, a partial is a sugar-coated template. Normally a template reference has a path specified. Partials are different. Hugo searches for them along a TODO defined search path. This makes it easier for end-users to override the theme\u0026rsquo;s presentation.\n$ vi themes/zafta/layouts/partials/header.html \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;title\u0026gt;{{ .Title }}\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; :wq $ vi themes/zafta/layouts/partials/footer.html \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; :wq Update the Home Page Template to Use the Partials # The most noticeable difference between a template call and a partials call is the lack of path:\n{{ template \u0026#34;theme/partials/header.html\u0026#34; . }} versus\n{{ partial \u0026#34;header.html\u0026#34; . }} Both pass in the context.\nLet\u0026rsquo;s change the home page template to use these new partials.\n$ vi themes/zafta/layouts/index.html {{ partial \u0026#34;header.html\u0026#34; . }} \u0026lt;h1\u0026gt;posts\u0026lt;/h1\u0026gt; {{ range first 10 .Data.Pages }} {{ if eq .Type \u0026#34;post\u0026#34;}} \u0026lt;h2\u0026gt;\u0026lt;a href=\u0026#34;{{ .Permalink }}\u0026#34;\u0026gt;{{ .Title }}\u0026lt;/a\u0026gt;\u0026lt;/h2\u0026gt; {{ end }} {{ end }} \u0026lt;h1\u0026gt;pages\u0026lt;/h1\u0026gt; {{ range .Data.Pages }} {{ if or (eq .Type \u0026#34;page\u0026#34;) (eq .Type \u0026#34;about\u0026#34;) }} \u0026lt;h2\u0026gt;\u0026lt;a href=\u0026#34;{{ .Permalink }}\u0026#34;\u0026gt;{{ .Type }} - {{ .Title }} - {{ .RelPermalink }}\u0026lt;/a\u0026gt;\u0026lt;/h2\u0026gt; {{ end }} {{ end }} {{ partial \u0026#34;footer.html\u0026#34; . }} :wq Generate the web site and verify the results. The title on the home page is now \u0026ldquo;your title here\u0026rdquo;, which comes from the \u0026ldquo;title\u0026rdquo; variable in the config.toml file.\nUpdate the Default Single Template to Use the Partials # $ vi themes/zafta/layouts/_default/single.html {{ partial \u0026#34;header.html\u0026#34; . }} \u0026lt;h1\u0026gt;{{ .Title }}\u0026lt;/h1\u0026gt; {{ .Content }} {{ partial \u0026#34;footer.html\u0026#34; . }} :wq Generate the web site and verify the results. The title on the posts and the about page should both reflect the value in the markdown file.\nAdd “Date Published” to Posts # It\u0026rsquo;s common to have posts display the date that they were written or published, so let\u0026rsquo;s add that. The front matter of our posts has a variable named \u0026ldquo;date.\u0026rdquo; It\u0026rsquo;s usually the date the content was created, but let\u0026rsquo;s pretend that\u0026rsquo;s the value we want to display.\nAdd “Date Published” to the Template # We\u0026rsquo;ll start by updating the template used to render the posts. The template code will look like:\n{{ .Date.Format \u0026#34;Mon, Jan 2, 2006\u0026#34; }} Posts use the default single template, so we\u0026rsquo;ll change that file.\n$ vi themes/zafta/layouts/_default/single.html {{ partial \u0026#34;header.html\u0026#34; . }} \u0026lt;h1\u0026gt;{{ .Title }}\u0026lt;/h1\u0026gt; \u0026lt;h2\u0026gt;{{ .Date.Format \u0026#34;Mon, Jan 2, 2006\u0026#34; }}\u0026lt;/h2\u0026gt; {{ .Content }} {{ partial \u0026#34;footer.html\u0026#34; . }} :wq Generate the web site and verify the results. The posts now have the date displayed in them. There\u0026rsquo;s a problem, though. The \u0026ldquo;about\u0026rdquo; page also has the date displayed.\nAs usual, there are a couple of ways to make the date display only on posts. We could do an \u0026ldquo;if\u0026rdquo; statement like we did on the home page. Another way would be to create a separate template for posts.\nThe \u0026ldquo;if\u0026rdquo; solution works for sites that have just a couple of content types. It aligns with the principle of \u0026ldquo;code for today,\u0026rdquo; too.\nLet\u0026rsquo;s assume, though, that we\u0026rsquo;ve made our site so complex that we feel we have to create a new template type. In Hugo-speak, we\u0026rsquo;re going to create a section template.\nLet\u0026rsquo;s restore the default single template before we forget.\n$ mkdir themes/zafta/layouts/post $ vi themes/zafta/layouts/_default/single.html {{ partial \u0026#34;header.html\u0026#34; . }} \u0026lt;h1\u0026gt;{{ .Title }}\u0026lt;/h1\u0026gt; {{ .Content }} {{ partial \u0026#34;footer.html\u0026#34; . }} :wq Now we\u0026rsquo;ll update the post\u0026rsquo;s version of the single template. If you remember Hugo\u0026rsquo;s rules, the template engine will use this version over the default.\n$ vi themes/zafta/layouts/post/single.html {{ partial \u0026#34;header.html\u0026#34; . }} \u0026lt;h1\u0026gt;{{ .Title }}\u0026lt;/h1\u0026gt; \u0026lt;h2\u0026gt;{{ .Date.Format \u0026#34;Mon, Jan 2, 2006\u0026#34; }}\u0026lt;/h2\u0026gt; {{ .Content }} {{ partial \u0026#34;footer.html\u0026#34; . }} :wq Note that we removed the date logic from the default template and put it in the post template. Generate the web site and verify the results. Posts have dates and the about page doesn\u0026rsquo;t.\nDon\u0026rsquo;t Repeat Yourself # DRY is a good design goal and Hugo does a great job supporting it. Part of the art of a good template is knowing when to add a new template and when to update an existing one. While you\u0026rsquo;re figuring that out, accept that you\u0026rsquo;ll be doing some refactoring. Hugo makes that easy and fast, so it\u0026rsquo;s okay to delay splitting up a template.\n"},{"id":4,"href":"/posts/migrate-from-jekyll/","title":"Migrating from Jekyll","section":"Blog","content":" Move static content to static # Jekyll has a rule that any directory not starting with _ will be copied as-is to the _site output. Hugo keeps all static content under static. You should therefore move it all there. With Jekyll, something that looked like\n▾ \u0026lt;root\u0026gt;/ ▾ images/ logo.png should become\n▾ \u0026lt;root\u0026gt;/ ▾ static/ ▾ images/ logo.png Additionally, you\u0026rsquo;ll want any files that should reside at the root (such as CNAME) to be moved to static.\nCreate your Hugo configuration file # Hugo can read your configuration as JSON, YAML or TOML. Hugo supports parameters custom configuration too. Refer to the Hugo configuration documentation for details.\nSet your configuration publish folder to _site # The default is for Jekyll to publish to _site and for Hugo to publish to public. If, like me, you have _site mapped to a git submodule on the gh-pages branch, you\u0026rsquo;ll want to do one of two alternatives:\nChange your submodule to point to map gh-pages to public instead of _site (recommended).\ngit submodule deinit _site git rm _site git submodule add -b gh-pages [email protected]:your-username/your-repo.git public Or, change the Hugo configuration to use _site instead of public.\n{ .. \u0026quot;publishdir\u0026quot;: \u0026quot;_site\u0026quot;, .. } Convert Jekyll templates to Hugo templates # That\u0026rsquo;s the bulk of the work right here. The documentation is your friend. You should refer to Jekyll\u0026rsquo;s template documentation if you need to refresh your memory on how you built your blog and Hugo\u0026rsquo;s template to learn Hugo\u0026rsquo;s way.\nAs a single reference data point, converting my templates for heyitsalex.net took me no more than a few hours.\nConvert Jekyll plugins to Hugo shortcodes # Jekyll has plugins; Hugo has shortcodes. It\u0026rsquo;s fairly trivial to do a port.\nImplementation # As an example, I was using a custom image_tag plugin to generate figures with caption when running Jekyll. As I read about shortcodes, I found Hugo had a nice built-in shortcode that does exactly the same thing.\nJekyll\u0026rsquo;s plugin:\nmodule Jekyll class ImageTag \u0026lt; Liquid::Tag @url = nil @caption = nil @class = nil @link = nil // Patterns IMAGE_URL_WITH_CLASS_AND_CAPTION = IMAGE_URL_WITH_CLASS_AND_CAPTION_AND_LINK = /(\\w+)(\\s+)((https?:\\/\\/|\\/)(\\S+))(\\s+)\u0026quot;(.*?)\u0026quot;(\\s+)-\u0026gt;((https?:\\/\\/|\\/)(\\S+))(\\s*)/i IMAGE_URL_WITH_CAPTION = /((https?:\\/\\/|\\/)(\\S+))(\\s+)\u0026quot;(.*?)\u0026quot;/i IMAGE_URL_WITH_CLASS = /(\\w+)(\\s+)((https?:\\/\\/|\\/)(\\S+))/i IMAGE_URL = /((https?:\\/\\/|\\/)(\\S+))/i def initialize(tag_name, markup, tokens) super if markup =~ IMAGE_URL_WITH_CLASS_AND_CAPTION_AND_LINK @class = $1 @url = $3 @caption = $7 @link = $9 elsif markup =~ IMAGE_URL_WITH_CLASS_AND_CAPTION @class = $1 @url = $3 @caption = $7 elsif markup =~ IMAGE_URL_WITH_CAPTION @url = $1 @caption = $5 elsif markup =~ IMAGE_URL_WITH_CLASS @class = $1 @url = $3 elsif markup =~ IMAGE_URL @url = $1 end end def render(context) if @class source = \u0026quot;\u0026lt;figure class='#{@class}'\u0026gt;\u0026quot; else source = \u0026quot;\u0026lt;figure\u0026gt;\u0026quot; end if @link source += \u0026quot;\u0026lt;a href=\\\u0026quot;#{@link}\\\u0026quot;\u0026gt;\u0026quot; end source += \u0026quot;\u0026lt;img src=\\\u0026quot;#{@url}\\\u0026quot;\u0026gt;\u0026quot; if @link source += \u0026quot;\u0026lt;/a\u0026gt;\u0026quot; end source += \u0026quot;\u0026lt;figcaption\u0026gt;#{@caption}\u0026lt;/figcaption\u0026gt;\u0026quot; if @caption source += \u0026quot;\u0026lt;/figure\u0026gt;\u0026quot; source end end end Liquid::Template.register_tag('image', Jekyll::ImageTag) is written as this Hugo shortcode:\n\u0026lt;!-- image --\u0026gt; \u0026lt;figure {{ with .Get \u0026quot;class\u0026quot; }}class=\u0026quot;{{.}}\u0026quot;{{ end }}\u0026gt; {{ with .Get \u0026quot;link\u0026quot;}}\u0026lt;a href=\u0026quot;{{.}}\u0026quot;\u0026gt;{{ end }} \u0026lt;img src=\u0026quot;{{ .Get \u0026quot;src\u0026quot; }}\u0026quot; {{ if or (.Get \u0026quot;alt\u0026quot;) (.Get \u0026quot;caption\u0026quot;) }}alt=\u0026quot;{{ with .Get \u0026quot;alt\u0026quot;}}{{.}}{{else}}{{ .Get \u0026quot;caption\u0026quot; }}{{ end }}\u0026quot;{{ end }} /\u0026gt; {{ if .Get \u0026quot;link\u0026quot;}}\u0026lt;/a\u0026gt;{{ end }} {{ if or (or (.Get \u0026quot;title\u0026quot;) (.Get \u0026quot;caption\u0026quot;)) (.Get \u0026quot;attr\u0026quot;)}} \u0026lt;figcaption\u0026gt;{{ if isset .Params \u0026quot;title\u0026quot; }} {{ .Get \u0026quot;title\u0026quot; }}{{ end }} {{ if or (.Get \u0026quot;caption\u0026quot;) (.Get \u0026quot;attr\u0026quot;)}}\u0026lt;p\u0026gt; {{ .Get \u0026quot;caption\u0026quot; }} {{ with .Get \u0026quot;attrlink\u0026quot;}}\u0026lt;a href=\u0026quot;{{.}}\u0026quot;\u0026gt; {{ end }} {{ .Get \u0026quot;attr\u0026quot; }} {{ if .Get \u0026quot;attrlink\u0026quot;}}\u0026lt;/a\u0026gt; {{ end }} \u0026lt;/p\u0026gt; {{ end }} \u0026lt;/figcaption\u0026gt; {{ end }} \u0026lt;/figure\u0026gt; \u0026lt;!-- image --\u0026gt; Usage # I simply changed:\n{% image full http://farm5.staticflickr.com/4136/4829260124_57712e570a_o_d.jpg \u0026quot;One of my favorite touristy-type photos. I secretly waited for the good light while we were \u0026quot;having fun\u0026quot; and took this. Only regret: a stupid pole in the top-left corner of the frame I had to clumsily get rid of at post-processing.\u0026quot; -\u0026gt;http://www.flickr.com/photos/alexnormand/4829260124/in/set-72157624547713078/ %} to this (this example uses a slightly extended version named fig, different than the built-in figure):\n{{% fig class=\u0026quot;full\u0026quot; src=\u0026quot;http://farm5.staticflickr.com/4136/4829260124_57712e570a_o_d.jpg\u0026quot; title=\u0026quot;One of my favorite touristy-type photos. I secretly waited for the good light while we were having fun and took this. Only regret: a stupid pole in the top-left corner of the frame I had to clumsily get rid of at post-processing.\u0026quot; link=\u0026quot;http://www.flickr.com/photos/alexnormand/4829260124/in/set-72157624547713078/\u0026quot; %}} As a bonus, the shortcode named parameters are, arguably, more readable.\nFinishing touches # Fix content # Depending on the amount of customization that was done with each post with Jekyll, this step will require more or less effort. There are no hard and fast rules here except that hugo server --watch is your friend. Test your changes and fix errors as needed.\nClean up # You\u0026rsquo;ll want to remove the Jekyll configuration at this point. If you have anything else that isn\u0026rsquo;t used, delete it.\nA practical example in a diff # Hey, it\u0026rsquo;s Alex was migrated in less than a father-with-kids day from Jekyll to Hugo. You can see all the changes (and screw-ups) by looking at this diff.\n"},{"id":5,"href":"/docs/topic/array/","title":"1.01 Array","section":"Topic","content":" Caput vino delphine in tamen vias # Cognita laeva illo fracta # Lorem markdownum pavent auras, surgit nunc cingentibus libet Laomedonque que est. Pastor An arbor filia foedat, ne fugit aliter, per. Helicona illas et callida neptem est Oresitrophos caput, dentibus est venit. Tenet reddite famuli praesentem fortibus, quaeque vis foret si frondes gelidos gravidae circumtulit inpulit armenta nativum.\nTe at cruciabere vides rubentis manebo Maturuit in praetemptat ruborem ignara postquam habitasse Subitarum supplevit quoque fontesque venabula spretis modo Montis tot est mali quasque gravis Quinquennem domus arsit ipse Pellem turis pugnabant locavit Natus quaerere # Pectora et sine mulcere, coniuge dum tincta incurvae. Quis iam; est dextra Peneosque, metuis a verba, primo. Illa sed colloque suis: magno: gramen, aera excutiunt concipit.\nPhrygiae petendo suisque extimuit, super, pars quod audet! Turba negarem. Fuerat attonitus; et dextra retinet sidera ulnas undas instimulat vacuae generis? Agnus dabat et ignotis dextera, sic tibi pacis feriente at mora euhoeque comites hostem vestras Phineus. Vultuque sanguine dominoque metuit risi fama vergit summaque meus clarissimus artesque tinguebat successor nominis cervice caelicolae.\nLimitibus misere sit # Aurea non fata repertis praerupit feruntur simul, meae hosti lentaque citius levibus, cum sede dixit, Phaethon texta. Albentibus summos multifidasque iungitur loquendi an pectore, mihi ursaque omnia adfata, aeno parvumque in animi perlucentes. Epytus agis ait vixque clamat ornum adversam spondet, quid sceptra ipsum est. Reseret nec; saeva suo passu debentia linguam terga et aures et cervix de ubera. Coercet gelidumque manus, doluit volvitur induta?\nEnim sua # Iuvenilior filia inlustre templa quidem herbis permittat trahens huic. In cruribus proceres sole crescitque fata, quos quos; merui maris se non tamen in, mea.\nGermana aves pignus tecta # Mortalia rudibusque caelum cognosceret tantum aquis redito felicior texit, nec, aris parvo acre. Me parum contulerant multi tenentem, gratissime suis; vultum tu occupat deficeret corpora, sonum. E Actaea inplevit Phinea concepit nomenque potest sanguine captam nulla et, in duxisses campis non; mercede. Dicere cur Leucothoen obitum?\nPostibus mittam est nubibus principium pluma, exsecratur facta et. Iunge Mnemonidas pallamque pars; vere restitit alis flumina quae quoque, est ignara infestus Pyrrha. Di ducis terris maculatum At sede praemia manes nullaque!\n"},{"id":6,"href":"/docs/topic/linked-list/","title":"1.02 Linked List","section":"Topic","content":" Problem Solution Difficulty Like 0002. Add Two Numbers Java Medium 0019. Remove Nth Node From End of List Java Medium 0021. Merge Two Sorted Lists Java Easy 0023. Merge k Sorted Lists Java Hard 😎 0024. Swap Nodes in Pairs Java Medium 0025. Reverse Nodes in k-Group Java Hard 😎 0061. Rotate List Java Medium 0082. Remove Duplicates from Sorted List II Java Medium 0083. Remove Duplicates from Sorted List Java Easy 0086. Partition List Java Medium 😎 0092. Reverse Linked List II Java Medium 😎 0138. Copy List with Random Pointer Java Medium 😎 0141. Linked List Cycle Java Easy 0142. Linked List Cycle II Java Medium 😎 0143. Reorder List Java Medium 😎 0146. LRU Cache Java Medium 😎 0147. Insertion Sort List Java Medium 0148. Sort List Medium 😎 0160. Intersection of Two Linked Lists Java Easy 😎 0203. Remove Linked List Elements Java Easy 0206. Reverse Linked List Java Easy 0234. Palindrome Linked List Java Easy 0237. Delete Node in a Linked List Java Medium 0328. Odd Even Linked List Java Medium 😎 0355. Design Twitter Java Medium 😎😎😎 0369. Plug One Linked List Java Medium 0379. Design Phone Directory Java Medium 0382. Linked List Random Node Java Medium 0430. Flatten a Multilevel Doubly Linked List Java Medium 😎 0432. All O`one Data Structure Java Hard 😎😎 0445. Add Two Numbers II Java Medium 0460. LFU Cache Java Hard 😎😎😎 0622. Design Circular Queue Java Medium 0641. Design Circular Deque Java Medium 0707. Design Linked List Java Medium 0708. Insert into a Sorted Circular Linked List Java Medium 😎😎 0716. Max Stack Java Hard 😎😎😎 0725. Split Linked List in Parts Java Medium 😎😎 0817. Linked List Components Java Medium 0876. Middle of the Linked List Java Easy 1019.Next Greater Node in Linked List Java Medium 1171. Remove Zero Sum Consecutive Nodes from Linked List Java Medium 😎😎 "},{"id":7,"href":"/docs/templates/reservoir/","title":"3.01 Random sampling with a reservoir","section":"Templates","content":" Caput vino delphine in tamen vias # Cognita laeva illo fracta # Lorem markdownum pavent auras, surgit nunc cingentibus libet Laomedonque que est. Pastor An arbor filia foedat, ne fugit aliter, per. Helicona illas et callida neptem est Oresitrophos caput, dentibus est venit. Tenet reddite famuli praesentem fortibus, quaeque vis foret si frondes gelidos gravidae circumtulit inpulit armenta nativum.\nTe at cruciabere vides rubentis manebo Maturuit in praetemptat ruborem ignara postquam habitasse Subitarum supplevit quoque fontesque venabula spretis modo Montis tot est mali quasque gravis Quinquennem domus arsit ipse Pellem turis pugnabant locavit Natus quaerere # Pectora et sine mulcere, coniuge dum tincta incurvae. Quis iam; est dextra Peneosque, metuis a verba, primo. Illa sed colloque suis: magno: gramen, aera excutiunt concipit.\nPhrygiae petendo suisque extimuit, super, pars quod audet! Turba negarem. Fuerat attonitus; et dextra retinet sidera ulnas undas instimulat vacuae generis? Agnus dabat et ignotis dextera, sic tibi pacis feriente at mora euhoeque comites hostem vestras Phineus. Vultuque sanguine dominoque metuit risi fama vergit summaque meus clarissimus artesque tinguebat successor nominis cervice caelicolae.\nLimitibus misere sit # Aurea non fata repertis praerupit feruntur simul, meae hosti lentaque citius levibus, cum sede dixit, Phaethon texta. Albentibus summos multifidasque iungitur loquendi an pectore, mihi ursaque omnia adfata, aeno parvumque in animi perlucentes. Epytus agis ait vixque clamat ornum adversam spondet, quid sceptra ipsum est. Reseret nec; saeva suo passu debentia linguam terga et aures et cervix de ubera. Coercet gelidumque manus, doluit volvitur induta?\nEnim sua # Iuvenilior filia inlustre templa quidem herbis permittat trahens huic. In cruribus proceres sole crescitque fata, quos quos; merui maris se non tamen in, mea.\nGermana aves pignus tecta # Mortalia rudibusque caelum cognosceret tantum aquis redito felicior texit, nec, aris parvo acre. Me parum contulerant multi tenentem, gratissime suis; vultum tu occupat deficeret corpora, sonum. E Actaea inplevit Phinea concepit nomenque potest sanguine captam nulla et, in duxisses campis non; mercede. Dicere cur Leucothoen obitum?\nPostibus mittam est nubibus principium pluma, exsecratur facta et. Iunge Mnemonidas pallamque pars; vere restitit alis flumina quae quoque, est ignara infestus Pyrrha. Di ducis terris maculatum At sede praemia manes nullaque!\n"},{"id":8,"href":"/docs/templates/LRU/","title":"3.02 LRU \u0026 LFU","section":"Templates","content":" Caput vino delphine in tamen vias # Cognita laeva illo fracta # Lorem markdownum pavent auras, surgit nunc cingentibus libet Laomedonque que est. Pastor An arbor filia foedat, ne fugit aliter, per. Helicona illas et callida neptem est Oresitrophos caput, dentibus est venit. Tenet reddite famuli praesentem fortibus, quaeque vis foret si frondes gelidos gravidae circumtulit inpulit armenta nativum.\nTe at cruciabere vides rubentis manebo Maturuit in praetemptat ruborem ignara postquam habitasse Subitarum supplevit quoque fontesque venabula spretis modo Montis tot est mali quasque gravis Quinquennem domus arsit ipse Pellem turis pugnabant locavit Natus quaerere # Pectora et sine mulcere, coniuge dum tincta incurvae. Quis iam; est dextra Peneosque, metuis a verba, primo. Illa sed colloque suis: magno: gramen, aera excutiunt concipit.\nPhrygiae petendo suisque extimuit, super, pars quod audet! Turba negarem. Fuerat attonitus; et dextra retinet sidera ulnas undas instimulat vacuae generis? Agnus dabat et ignotis dextera, sic tibi pacis feriente at mora euhoeque comites hostem vestras Phineus. Vultuque sanguine dominoque metuit risi fama vergit summaque meus clarissimus artesque tinguebat successor nominis cervice caelicolae.\nLimitibus misere sit # Aurea non fata repertis praerupit feruntur simul, meae hosti lentaque citius levibus, cum sede dixit, Phaethon texta. Albentibus summos multifidasque iungitur loquendi an pectore, mihi ursaque omnia adfata, aeno parvumque in animi perlucentes. Epytus agis ait vixque clamat ornum adversam spondet, quid sceptra ipsum est. Reseret nec; saeva suo passu debentia linguam terga et aures et cervix de ubera. Coercet gelidumque manus, doluit volvitur induta?\nEnim sua # Iuvenilior filia inlustre templa quidem herbis permittat trahens huic. In cruribus proceres sole crescitque fata, quos quos; merui maris se non tamen in, mea.\nGermana aves pignus tecta # Mortalia rudibusque caelum cognosceret tantum aquis redito felicior texit, nec, aris parvo acre. Me parum contulerant multi tenentem, gratissime suis; vultum tu occupat deficeret corpora, sonum. E Actaea inplevit Phinea concepit nomenque potest sanguine captam nulla et, in duxisses campis non; mercede. Dicere cur Leucothoen obitum?\nPostibus mittam est nubibus principium pluma, exsecratur facta et. Iunge Mnemonidas pallamque pars; vere restitit alis flumina quae quoque, est ignara infestus Pyrrha. Di ducis terris maculatum At sede praemia manes nullaque!\n"},{"id":9,"href":"/posts/goisforlovers/","title":"(Hu)go Template Primer","section":"Blog","content":"Hugo uses the excellent Go html/template library for its template engine. It is an extremely lightweight engine that provides a very small amount of logic. In our experience that it is just the right amount of logic to be able to create a good static website. If you have used other template systems from different languages or frameworks you will find a lot of similarities in Go templates.\nThis document is a brief primer on using Go templates. The Go docs provide more details.\nIntroduction to Go Templates # Go templates provide an extremely simple template language. It adheres to the belief that only the most basic of logic belongs in the template or view layer. One consequence of this simplicity is that Go templates parse very quickly.\nA unique characteristic of Go templates is they are content aware. Variables and content will be sanitized depending on the context of where they are used. More details can be found in the Go docs.\nBasic Syntax # Golang templates are HTML files with the addition of variables and functions.\nGo variables and functions are accessible within {{ }}\nAccessing a predefined variable \u0026ldquo;foo\u0026rdquo;:\n{{ foo }} Parameters are separated using spaces\nCalling the add function with input of 1, 2:\n{{ add 1 2 }} Methods and fields are accessed via dot notation\nAccessing the Page Parameter \u0026ldquo;bar\u0026rdquo;\n{{ .Params.bar }} Parentheses can be used to group items together\n{{ if or (isset .Params \u0026quot;alt\u0026quot;) (isset .Params \u0026quot;caption\u0026quot;) }} Caption {{ end }} Variables # Each Go template has a struct (object) made available to it. In hugo each template is passed either a page or a node struct depending on which type of page you are rendering. More details are available on the variables page.\nA variable is accessed by referencing the variable name.\n\u0026lt;title\u0026gt;{{ .Title }}\u0026lt;/title\u0026gt; Variables can also be defined and referenced.\n{{ $address := \u0026quot;123 Main St.\u0026quot;}} {{ $address }} Functions # Go template ship with a few functions which provide basic functionality. The Go template system also provides a mechanism for applications to extend the available functions with their own. Hugo template functions provide some additional functionality we believe are useful for building websites. Functions are called by using their name followed by the required parameters separated by spaces. Template functions cannot be added without recompiling hugo.\nExample:\n{{ add 1 2 }} Includes # When including another template you will pass to it the data it will be able to access. To pass along the current context please remember to include a trailing dot. The templates location will always be starting at the /layout/ directory within Hugo.\nExample:\n{{ template \u0026quot;chrome/header.html\u0026quot; . }} Logic # Go templates provide the most basic iteration and conditional logic.\nIteration # Just like in Go, the Go templates make heavy use of range to iterate over a map, array or slice. The following are different examples of how to use range.\nExample 1: Using Context\n{{ range array }} {{ . }} {{ end }} Example 2: Declaring value variable name\n{{range $element := array}} {{ $element }} {{ end }} Example 2: Declaring key and value variable name\n{{range $index, $element := array}} {{ $index }} {{ $element }} {{ end }} Conditionals # If, else, with, or, \u0026amp; and provide the framework for handling conditional logic in Go Templates. Like range, each statement is closed with end.\nGo Templates treat the following values as false:\nfalse 0 any array, slice, map, or string of length zero Example 1: If\n{{ if isset .Params \u0026quot;title\u0026quot; }}\u0026lt;h4\u0026gt;{{ index .Params \u0026quot;title\u0026quot; }}\u0026lt;/h4\u0026gt;{{ end }} Example 2: If -\u0026gt; Else\n{{ if isset .Params \u0026quot;alt\u0026quot; }} {{ index .Params \u0026quot;alt\u0026quot; }} {{else}} {{ index .Params \u0026quot;caption\u0026quot; }} {{ end }} Example 3: And \u0026amp; Or\n{{ if and (or (isset .Params \u0026quot;title\u0026quot;) (isset .Params \u0026quot;caption\u0026quot;)) (isset .Params \u0026quot;attr\u0026quot;)}} Example 4: With\nAn alternative way of writing \u0026ldquo;if\u0026rdquo; and then referencing the same value is to use \u0026ldquo;with\u0026rdquo; instead. With rebinds the context . within its scope, and skips the block if the variable is absent.\nThe first example above could be simplified as:\n{{ with .Params.title }}\u0026lt;h4\u0026gt;{{ . }}\u0026lt;/h4\u0026gt;{{ end }} Example 5: If -\u0026gt; Else If\n{{ if isset .Params \u0026quot;alt\u0026quot; }} {{ index .Params \u0026quot;alt\u0026quot; }} {{ else if isset .Params \u0026quot;caption\u0026quot; }} {{ index .Params \u0026quot;caption\u0026quot; }} {{ end }} Pipes # One of the most powerful components of Go templates is the ability to stack actions one after another. This is done by using pipes. Borrowed from unix pipes, the concept is simple, each pipeline\u0026rsquo;s output becomes the input of the following pipe.\nBecause of the very simple syntax of Go templates, the pipe is essential to being able to chain together function calls. One limitation of the pipes is that they only can work with a single value and that value becomes the last parameter of the next pipeline.\nA few simple examples should help convey how to use the pipe.\nExample 1 :\n{{ if eq 1 1 }} Same {{ end }} is the same as\n{{ eq 1 1 | if }} Same {{ end }} It does look odd to place the if at the end, but it does provide a good illustration of how to use the pipes.\nExample 2 :\n{{ index .Params \u0026quot;disqus_url\u0026quot; | html }} Access the page parameter called \u0026ldquo;disqus_url\u0026rdquo; and escape the HTML.\nExample 3 :\n{{ if or (or (isset .Params \u0026quot;title\u0026quot;) (isset .Params \u0026quot;caption\u0026quot;)) (isset .Params \u0026quot;attr\u0026quot;)}} Stuff Here {{ end }} Could be rewritten as\n{{ isset .Params \u0026quot;caption\u0026quot; | or isset .Params \u0026quot;title\u0026quot; | or isset .Params \u0026quot;attr\u0026quot; | if }} Stuff Here {{ end }} Context (aka. the dot) # The most easily overlooked concept to understand about Go templates is that {{ . }} always refers to the current context. In the top level of your template this will be the data set made available to it. Inside of a iteration it will have the value of the current item. When inside of a loop the context has changed. . will no longer refer to the data available to the entire page. If you need to access this from within the loop you will likely want to set it to a variable instead of depending on the context.\nExample:\n{{ $title := .Site.Title }} {{ range .Params.tags }} \u0026lt;li\u0026gt; \u0026lt;a href=\u0026quot;{{ $baseurl }}/tags/{{ . | urlize }}\u0026quot;\u0026gt;{{ . }}\u0026lt;/a\u0026gt; - {{ $title }} \u0026lt;/li\u0026gt; {{ end }} Notice how once we have entered the loop the value of {{ . }} has changed. We have defined a variable outside of the loop so we have access to it from within the loop.\nHugo Parameters # Hugo provides the option of passing values to the template language through the site configuration (for sitewide values), or through the meta data of each specific piece of content. You can define any values of any type (supported by your front matter/config format) and use them however you want to inside of your templates.\nUsing Content (page) Parameters # In each piece of content you can provide variables to be used by the templates. This happens in the front matter.\nAn example of this is used in this documentation site. Most of the pages benefit from having the table of contents provided. Sometimes the TOC just doesn\u0026rsquo;t make a lot of sense. We\u0026rsquo;ve defined a variable in our front matter of some pages to turn off the TOC from being displayed.\nHere is the example front matter:\n--- title: \u0026#34;Permalinks\u0026#34; date: \u0026#34;2013-11-18\u0026#34; aliases: - \u0026#34;/doc/permalinks/\u0026#34; groups: [\u0026#34;extras\u0026#34;] groups_weight: 30 notoc: true --- Here is the corresponding code inside of the template:\n{{ if not .Params.notoc }} \u0026lt;div id=\u0026quot;toc\u0026quot; class=\u0026quot;well col-md-4 col-sm-6\u0026quot;\u0026gt; {{ .TableOfContents }} \u0026lt;/div\u0026gt; {{ end }} Using Site (config) Parameters # In your top-level configuration file (eg, config.yaml) you can define site parameters, which are values which will be available to you in chrome.\nFor instance, you might declare:\nparams: CopyrightHTML: \u0026#34;Copyright \u0026amp;#xA9; 2013 John Doe. All Rights Reserved.\u0026#34; TwitterUser: \u0026#34;spf13\u0026#34; SidebarRecentLimit: 5 Within a footer layout, you might then declare a \u0026lt;footer\u0026gt; which is only provided if the CopyrightHTML parameter is provided, and if it is given, you would declare it to be HTML-safe, so that the HTML entity is not escaped again. This would let you easily update just your top-level config file each January 1st, instead of hunting through your templates.\n{{if .Site.Params.CopyrightHTML}}\u0026lt;footer\u0026gt; \u0026lt;div class=\u0026#34;text-center\u0026#34;\u0026gt;{{.Site.Params.CopyrightHTML | safeHtml}}\u0026lt;/div\u0026gt; \u0026lt;/footer\u0026gt;{{end}} An alternative way of writing the \u0026ldquo;if\u0026rdquo; and then referencing the same value is to use \u0026ldquo;with\u0026rdquo; instead. With rebinds the context . within its scope, and skips the block if the variable is absent:\n{{with .Site.Params.TwitterUser}}\u0026lt;span class=\u0026#34;twitter\u0026#34;\u0026gt; \u0026lt;a href=\u0026#34;https://twitter.com/{{.}}\u0026#34; rel=\u0026#34;author\u0026#34;\u0026gt; \u0026lt;img src=\u0026#34;/images/twitter.png\u0026#34; width=\u0026#34;48\u0026#34; height=\u0026#34;48\u0026#34; title=\u0026#34;Twitter: {{.}}\u0026#34; alt=\u0026#34;Twitter\u0026#34;\u0026gt;\u0026lt;/a\u0026gt; \u0026lt;/span\u0026gt;{{end}} Finally, if you want to pull \u0026ldquo;magic constants\u0026rdquo; out of your layouts, you can do so, such as in this example:\n\u0026lt;nav class=\u0026#34;recent\u0026#34;\u0026gt; \u0026lt;h1\u0026gt;Recent Posts\u0026lt;/h1\u0026gt; \u0026lt;ul\u0026gt;{{range first .Site.Params.SidebarRecentLimit .Site.Recent}} \u0026lt;li\u0026gt;\u0026lt;a href=\u0026#34;{{.RelPermalink}}\u0026#34;\u0026gt;{{.Title}}\u0026lt;/a\u0026gt;\u0026lt;/li\u0026gt; {{end}}\u0026lt;/ul\u0026gt; \u0026lt;/nav\u0026gt; "},{"id":10,"href":"/posts/hugoisforlovers/","title":"Getting Started with Hugo","section":"Blog","content":" Step 1. Install Hugo # Go to Hugo releases and download the appropriate version for your OS and architecture.\nSave it somewhere specific as we will be using it in the next step.\nMore complete instructions are available at Install Hugo\nStep 2. Build the Docs # Hugo has its own example site which happens to also be the documentation site you are reading right now.\nFollow the following steps:\nClone the Hugo repository Go into the repo Run hugo in server mode and build the docs Open your browser to http://localhost:1313 Corresponding pseudo commands:\ngit clone https://github.com/spf13/hugo cd hugo /path/to/where/you/installed/hugo server --source=./docs \u0026gt; 29 pages created \u0026gt; 0 tags index created \u0026gt; in 27 ms \u0026gt; Web Server is available at http://localhost:1313 \u0026gt; Press ctrl+c to stop Once you\u0026rsquo;ve gotten here, follow along the rest of this page on your local build.\nStep 3. Change the docs site # Stop the Hugo process by hitting Ctrl+C.\nNow we are going to run hugo again, but this time with hugo in watch mode.\n/path/to/hugo/from/step/1/hugo server --source=./docs --watch \u0026gt; 29 pages created \u0026gt; 0 tags index created \u0026gt; in 27 ms \u0026gt; Web Server is available at http://localhost:1313 \u0026gt; Watching for changes in /Users/spf13/Code/hugo/docs/content \u0026gt; Press ctrl+c to stop Open your favorite editor and change one of the source content pages. How about changing this very file to fix the typo. How about changing this very file to fix the typo.\nContent files are found in docs/content/. Unless otherwise specified, files are located at the same relative location as the url, in our case docs/content/overview/quickstart.md.\nChange and save this file.. Notice what happened in your terminal.\n\u0026gt; Change detected, rebuilding site \u0026gt; 29 pages created \u0026gt; 0 tags index created \u0026gt; in 26 ms Refresh the browser and observe that the typo is now fixed.\nNotice how quick that was. Try to refresh the site before it\u0026rsquo;s finished building. I double dare you. Having nearly instant feedback enables you to have your creativity flow without waiting for long builds.\nStep 4. Have fun # The best way to learn something is to play with it.\n"},{"id":11,"href":"/docs/codes/0001-to-0099/0001.-Two-Sum/","title":"0001. Two Sum","section":"0001 to 0099","content":" 1. Two Sum # 题目 # 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的 两个 整数,并返回它们的数组下标。\n思路 # 代码 # class Solution { public int[] twoSum(int[] nums, int target) { int[] result = new int[]{-1, -1}; Map\u0026lt;Integer, Integer\u0026gt; map = new HashMap\u0026lt;\u0026gt;(); for (int i=0; i\u0026lt;nums.length; i++) { if (map.containsKey(target-nums[i]) == true) { result[0] = map.get(target-nums[i]); result[1] = i; } else map.put(nums[i], i); } return result; } } "},{"id":12,"href":"/docs/codes/0001-to-0099/0002.-Add-Two-Numbers/","title":"0002. Add Two Numbers","section":"0001 to 0099","content":" 2. Add Two Numbers # 题目 # 给定两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。 将两个数相加,并以相同形式返回一个表示和的链表。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode helper(ListNode l1, ListNode l2, int carry) { if (l1 == null \u0026amp;\u0026amp; l2 == null) { return carry != 0 ? new ListNode(carry, null) : null; } else if (l1 != null \u0026amp;\u0026amp; l2 == null) { return new ListNode((l1.val + carry) % 10, helper(l1.next, null, (l1.val + carry) / 10)); } else if (l1 == null \u0026amp;\u0026amp; l2 != null) { return new ListNode((l2.val + carry) % 10, helper(null, l2.next, (l2.val + carry) / 10)); } else { ListNode head = new ListNode((l1.val + l2.val + carry) % 10, null); head.next = helper(l1.next, l2.next, (l1.val + l2.val + carry) / 10); return head; } } public ListNode addTwoNumbers(ListNode l1, ListNode l2) { return helper(l1, l2, 0); } } "},{"id":13,"href":"/docs/codes/0001-to-0099/0019.-Remove-Nth-Node-from-End-of-List/","title":"0019. Remove Nth Node From End of List","section":"0001 to 0099","content":" 19. Remove Nth Node from End of List # 题目 # 给定链表,要求删除链表的倒数第 n 个结点,并且返回链表的头结点。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { ListNode sentinel = new ListNode(-1, head); ListNode slow = sentinel, fast = slow; for (int i=0; i\u0026lt;n+1; i++) fast = fast.next; while (fast != null) { slow = slow.next; fast = fast.next; slow.next = slow.next.next; } return sentinel.next; } } "},{"id":14,"href":"/docs/codes/0001-to-0099/0021.-Merge-Two-Sorted-Lists/","title":"0021. Merge Two Sorted Lists","section":"0001 to 0099","content":" 21. 合并两个有序链表 # 题目 # 将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode mergeTwoLists(ListNode list1, ListNode list2) { if (list1 == null) return list2; if (list2 == null) return list1; if (list1.val \u0026lt; list2.val) { list1.next = mergeTwoLists(list1.next, list2); return list1; } else { list2.next = mergeTwoLists(list1, list2.next); return list2; } } } "},{"id":15,"href":"/docs/codes/0001-to-0099/0023.-Merge-K-Sorted-Lists/","title":"0023. Merge K Sorted Lists","section":"0001 to 0099","content":" 23. 合并K个升序链表 # 题目 # 给定一个链表数组,每个链表都已经按升序排列。\n将所有链表合并到一个升序链表中,返回合并后的链表。\n思路 # 构造大小为 K 的小根堆 建立堆结点和链表结点的映射 堆结点与链表结点共享变量 val 每次在堆中取最小值的结点,根据映射查找到相应链表节点,并加入到已有链表末尾。 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { private class HeapNode implements Comparable\u0026lt;HeapNode\u0026gt; { public int val; public ListNode ptr; HeapNode(int val, ListNode ptr) { this.val = val; this.ptr = ptr; } public int compareTo(HeapNode other) { /** 负值的 case, 对应将当前结点排在 other 结点之前 */ return this.val - other.val; } } private PriorityQueue\u0026lt;HeapNode\u0026gt; queue = new PriorityQueue\u0026lt;\u0026gt;(); public ListNode mergeKLists(ListNode[] lists) { ListNode sentinel = new ListNode(-1, null); ListNode ptr = sentinel; /** 初始化优先级队列 */ for (ListNode head: lists) { if (head != null) { HeapNode node = new HeapNode(head.val, head); this.queue.offer(node); } } /** 迭代直至优先级队列为空 */ while (this.queue.size() != 0) { HeapNode node = this.queue.poll(); ListNode head = node.ptr; ptr = ptr.next = head; if (head.next != null) { node = new HeapNode(head.next.val, head.next); this.queue.offer(node); } } return sentinel.next; } } 致谢 # 力扣官方题解\n"},{"id":16,"href":"/docs/codes/0001-to-0099/0024.-Swap-Nodes-in-pairs/","title":"0024. Swap Nodes in Pairs","section":"0001 to 0099","content":" 24. Swap Nodes in Pairs # 题目 # 给定链表,两两交换其中相邻的节点,并返回交换后链表的头节点。只能进行节点交换,不能修改节点内部的值。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode swapPairs(ListNode head) { if (head == null || head.next == null) return head; else { ListNode newHead = head.next; head.next = swapPairs(newHead.next); newHead.next = head; return newHead; } } } "},{"id":17,"href":"/docs/codes/0001-to-0099/0025.-Reverse-Nodes-in-K-Group/","title":"0025. Reverse Nodes in K Group","section":"0001 to 0099","content":" 25. Reverse Nodes in K Group # 题目 # 给定链表头结点 head,每 k 个结点一组进行翻转,返回修改后的链表。\nk 是一个正整数,它的值小于或等于链表的长度。如果结点总数不是 k 的整数倍,将最后的结点保持原有顺序。\n不能只是单纯的改变结点内部的值,而是需要进行实际的结点交换。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public void reverseList(ListNode beforeHead, ListNode tail) { if (beforeHead == tail) return; ListNode afterTail = tail.next; ListNode prev = afterTail, cur = beforeHead.next, temp = cur.next; while (cur != afterTail) { cur.next = prev; prev = cur; cur = temp; if (temp != afterTail) temp = temp.next; } beforeHead.next = prev; } public ListNode reverseKGroup(ListNode head, int k) { ListNode sentinel = new ListNode(-1, head); ListNode beforeHead = sentinel, tail = sentinel; while (tail != null) { for (int i = 0; i \u0026lt; k \u0026amp;\u0026amp; tail != null; i++) tail = tail.next; if (tail == null) return sentinel.next; /** ptr 指向翻转后的链表尾结点 */ ListNode ptr = beforeHead.next; reverseList(beforeHead, tail); beforeHead = tail = ptr; } return sentinel.next; } } "},{"id":18,"href":"/docs/codes/0001-to-0099/0027.-Remove-Element/","title":"0027. Remove Element","section":"0001 to 0099","content":" 27. Remove Element # 题目 # 给定一个数组nums和一个值val,原地移除所有值等于val的元素,并返回移除后数组的新长度。\n要求使用O(1)额外空间并原地修改输入数组。\n思路 # 代码 # class Solution { public int removeElements(int[] nums, int val) { int sz = 0; for (int ptr = 0; ptr \u0026lt; nums.length; ptr++) if (nums[ptr] != val) nums[sz++] = nums[ptr]; return sz; } } "},{"id":19,"href":"/docs/codes/0001-to-0099/0054.-Spiral-Matrix/","title":"0054. Spiral Matrix","section":"0001 to 0099","content":" 54. Spiral Matrix # 题目 # 给定一个m行n列的矩阵matrix,按照顺时针螺旋顺序,返回矩阵中的所有元素。\n思路 # 代码 # class Solution { public void circle(int[][] matrix, List\u0026lt;Integer\u0026gt; result, int top, int left, int right, int bottom) { if (top \u0026gt; bottom || left \u0026gt; right) return; if (top == bottom) { for (int j=left; j\u0026lt;=right; j++) result.add(matrix[top][j]); return; } else if (left == right) { for (int i=top; i\u0026lt;=bottom; i++) result.add(matrix[i][left]); return; } for (int j=left; j\u0026lt;right; j++) result.add(matrix[top][j]); for (int i=top; i\u0026lt;bottom; i++) result.add(matrix[i][right]); for (int j=right; j\u0026gt;left; j--) result.add(matrix[bottom][j]); for (int i=bottom; i\u0026gt;top; i--) result.add(matrix[i][left]); circle(matrix, result, top+1, left+1, right-1, bottom-1); } public List\u0026lt;Integer\u0026gt; spiralOrder(int[][] matrix) { int m = matrix.length, n = matrix[0].length; List\u0026lt;Integer\u0026gt; result = new ArrayList\u0026lt;Integer\u0026gt;(); circle(matrix, result, 0, 0, n-1, m-1); return result; } } 致谢 # 宫水三叶 "},{"id":20,"href":"/docs/codes/0001-to-0099/0059.-Spiral-Matrix-ii/","title":"0059. Spiral Matrix Ii","section":"0001 to 0099","content":" 59. Spiral Matrix II # 题目 # 给定正整数n,生成一个包含1到n^2所有元素,且元素按顺时针顺序螺旋排列的nxn正方形矩阵matrix。\n思路 # 对于n阶方阵,共有n/2个完整螺旋。\n若n为奇数,则matrix[n/2][n/2]处存在独立元素n^2,不构成螺旋,应单独考虑。\n对于第offset个螺旋,考虑四角元素的坐标,由左上顺时针分别为:\n(offset, offset)、(offset, n-offset-1)、(n-offset-1, n-offset-1)、(n-offset-1, offset)\n分别添加螺旋[上]、螺旋[右]、螺旋[下]、螺旋[左]四条边的元素,添加过程中保持区间左闭右开的一致性。\n代码 # class Solution { public int[][] generateMatrix(int n) { int[][] matrix = new int [n][n]; int val = 1; for (int offset=0; offset\u0026lt;n/2; offset++) { for (int j=offset; j\u0026lt;n-offset-1; j++) matrix[offset][j] = val++; for (int i=offset; i\u0026lt;n-offset-1; i++) matrix[i][n-offset-1] = val++; for (int j=n-offset-1; j\u0026gt;offset; j--) matrix[n-offset-1][j] = val++; for (int i=n-offset-1; i\u0026gt;offset; i--) matrix[i][offset] = val++; } if (n % 2 == 1) matrix[n/2][n/2] = n*n; return matrix; } } "},{"id":21,"href":"/docs/codes/0001-to-0099/0061.-Rotate-List/","title":"0061. Rotate List","section":"0001 to 0099","content":" 61. Rotate List # 题目 # 给定链表头节点head,旋转链表,将链表每个节点向右移动k个位置。\n思路 # 使用指针ptr统计链表长度n。 若k % n == 0,等价于不旋转链表。 将链表尾部节点rear与头节点head相连,即ptr.next = head,链表构成环。 设给定链表长度为n,将链表每个节点向右移动k个位置,等价于将链表每个节点向右移动k%n个位置。此时第n+1-k%n个节点将作为newHead。 令ptr指向第n-k%n个节点,在此处令ptr.next = null以断开环,并返回newHead。 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode rotateRight(ListNode head, int k) { if (head == null) return null; ListNode ptr = head; int length = 1; while (ptr.next != null) { ptr = ptr.next; length += 1; } if (k % length == 0) return head; ptr.next = head; for (int i=0; i\u0026lt;length - k % length, i++) ptr = ptr.next; ListNode newHead = ptr.next; ptr.next = null; return newHead; } } 致谢 # 力扣官方题解\n"},{"id":22,"href":"/docs/codes/0001-to-0099/0082.-Remove-Duplicates-from-Sorted-List-ii/","title":"0082. Remove Duplicates From Sorted List Ii","section":"0001 to 0099","content":" 82. Remove Duplicates from Sorted List II # 题目 # 给定排序链表的头节点head,删除原始链表中所有重复数字的节点,只留下不同的数字。返回已排序的链表。\n链表数据保证链表已经按升序排列。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode deleteDuplicates(ListNode head) { ListNode sentinel = new ListNode(-1, null); ListNode preserve = sentinel, anchor = head; while (anchor != null) { ListNode probe = anchor.next; if (probe == null || probe.val != anchor.val) { preserve.next = anchor; preserve = anchor; preserve.next = null; } else while (probe != null \u0026amp;\u0026amp; probe.val == anchor.val) probe = probe.next; anchor = probe; } return sentinel.next; } } "},{"id":23,"href":"/docs/codes/0001-to-0099/0083.-Remove-Duplicates-from-Sorted-List/","title":"0083. Remove Duplicates From Sorted List","section":"0001 to 0099","content":" 83. Remove Duplicates from Sorted List # 题目 # 给定排序链表的头节点head,删除所有重复元素,使每个元素只出现一次。返回已排序的链表。\n链表数据保证链表已经按升序排列。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode deleteDuplicates(ListNode head) { ListNode ptr = head; while (ptr != null \u0026amp;\u0026amp; ptr.next != null) { if (ptr.next.val == ptr.val) ptr.next = ptr.next.next; else ptr = ptr.next; } return head; } } "},{"id":24,"href":"/docs/codes/0001-to-0099/0086.-Partition-List/","title":"0086. Partition List","section":"0001 to 0099","content":" 86. Partition List # 题目 # 给定链表头节点head和一个特定值x,对链表进行分隔,使得所有小于x的节点都出现在大于或等于x的节点之前。应保留两个分区中每个节点的初始相对位置。\n思路 # 定位第一个值小于x的节点的前驱节点secLessLast,以及第一个值不小于x的节点secMoreFirst 设置preserve指针,指向当前secMore分区的最后一个节点 移动preserve指针,每次查看preserve指针的下一个节点,若其值小于x,则将此节点设置为新的secLessLast节点 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode partition(ListNode head, int x) { ListNode sentinel = new ListNode(-1, head); ListNode secLessLast = sentinel; while (secLessLast.next != null \u0026amp;\u0026amp; secLessLast.next.val \u0026lt; x) secLessLast = secLessLast.next; ListNode secMoreFirst = secLessLast.next; ListNode preserve = secMoreFirst; while (preserve != null \u0026amp;\u0026amp; preserve.next != null) { if (preserve.next.val \u0026gt;= x) preserve = preserve.next; else { ListNode ptr = preserve.next; preserve.next = ptr.next; secLessLast.next = ptr; ptr.next = secMoreFirst; secLessLast = ptr; } } return sentinel.next; } } "},{"id":25,"href":"/docs/codes/0001-to-0099/0092.-Reverse-Linked-List-ii/","title":"0092. Reverse Linked List Ii","section":"0001 to 0099","content":" 92. Reverse Linked List ii # 题目 # 给定单链表头节点head和两个整数left和right,其中left \u0026lt;= right。反转从位置left到位置right的链表节点,返回反转后的链表。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public void reverseList(ListNode head, ListNode tail) { if (head == tail) return; reverseList(head.next, tail); head.next.next = head; } public ListNode reverseBetween(ListNode head, int left, int right) { ListNode sentinel = new ListNode(-1, head); ListNode beforeLeft = sentinel, ptrRight = sentinel; for (int i=0; i\u0026lt;left-1; i++) beforeLeft = beforeLeft.next; for (int i=0; i\u0026lt;right; i++) ptrRight = ptrRight.next; ListNode ptrLeft = beforeLeft.next, afterRight = ptrRight.next; reverseList(ptrLeft, ptrRight); beforeLeft.next = ptrRight; ptrLeft.next = afterRight; return sentinel.next; } } "},{"id":26,"href":"/docs/codes/0100-to-0199/0138.-Copy-List-with-Random-Pointer/","title":"0138. Copy List With Random Pointer","section":"0100 to 0199","content":" 138. Copy List with Random Pointer # 题目 # 给定长度为 n 的链表,每个节点包含一个额外增加的随机指针 random,该指针可以指向链表中的任何节点或空节点。\n构造这个链表的 深拷贝。\n思路 # 通过两次遍历实现深拷贝。\n第一趟遍历,为新链表逐个生成节点,并构建新旧链表节点之间的对应关系。 第二趟遍历,为新链表深复制随机指针。 代码 # class Node { int val; Node next; Node random; public Node(int val) { this.val = val; this.next = null; this.random = null; } } class Solution { public Node copyRandomList(Node head) { Node sentinelOld = new Node(-1); sentinelOld.next = head; Node sentinelNew = new Node(-1); Node ptrOld = sentinelOld, ptrNew = sentinelNew; HashMap\u0026lt;Node, Node\u0026gt; correspond = new HashMap\u0026lt;Node, Node\u0026gt;(); while (ptrOld.next != null) { ptrNew.next = new Node(ptrOld.next.val); correspond.put(ptrOld.next, ptrNew.next); ptrOld = ptrOld.next; ptrNew = ptrNew.next; } ptrOld = sentinelOld; ptrNew = sentinelNew; while (ptrOld.next != null) { if (ptrOld.next.random == null) ptrNew.next.random = null; else ptrNew.next.random = correspond.get(ptrOld.next.random); ptrOld = ptrOld.next; ptrNew = ptrNew.next; } return sentinelNew.next; } } "},{"id":27,"href":"/docs/codes/0100-to-0199/0141.-Linked-List-Cycle/","title":"0141. Linked List Cycle","section":"0100 to 0199","content":" 141. Linked List Cycle # 题目 # 给定链表头节点 head ,判断链表中是否有环。\n如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。\n如果链表中存在环 ,则返回 true 。 否则,返回 false 。\n思路 # 代码 # class ListNode { int val; ListNode next; ListNode (int x) { val = x; next = null; } } public class Solution { public boolean hasCycle(ListNode head) { ListNode slow=head, fast=head; while (fast != null \u0026amp;\u0026amp; fast.next != null) { fast = fast.next.next; slow = slow.next; if (slow == fast) return true; } return false; } } "},{"id":28,"href":"/docs/codes/0100-to-0199/0142.-Linked-List-Cycle-ii/","title":"0142. Linked List Cycle Ii","section":"0100 to 0199","content":" 142. Linked List Cycle II # 题目 # 给定链表头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。\n不允许修改 链表。\n思路 # 设head至环入口距离为x,环入口至相遇处距离为y,相遇处至环入口距离为z assert: 相遇时slow指针在环内尚未走过完整的一圈。 proof: 若slow指针在环入口处与fast指针相遇,则此时slow指针尚未走过完整的一圈。若slow指针在环入口处尚未与fast指针相遇,则此时slow指针与fast指针的相对距离小于一圈,又因为fast指针追击slow指针的相对速度为1,则在slow指针尚未走过一圈的时间内,fast指针就将追击slow指针。故相遇时slow指针在环内尚未走过完整的一圈。 相遇时slow指针走过的距离可表示为x+y,fast指针走过的距离可表示为x+n(y+z)+y 有等式2(x+y) = x+y+n(y+z),化简有x=(n-1)(y+z) + z 新建指针ptr指向head。令fast指针与ptr指针同时以速度1向前移动,则fast指针与ptr指针将在环入口处相遇。 代码 # class ListNode { int val; ListNode next; ListNode (int x) { val = x; next = null; } } public class Solution { public ListNode detectCycle(ListNode head) { ListNode slow = head, fast = head; while (fast != null \u0026amp;\u0026amp; fast.next != null) { fast = fast.next.next; slow = slow.next; if (slow == fast) { ListNode ptr = head; while (ptr != fast) { ptr = ptr.next; fast = fast.next; } return fase; } } return null; } } "},{"id":29,"href":"/docs/codes/0100-to-0199/0143.-Reorder-List/","title":"0143. Reorder List","section":"0100 to 0199","content":" 143. Reorder List # 题目 # 给定一个单链表 L 的头节点 head ,单链表 L 表示为:\nL0 → L1 → … → Ln - 1 → Ln 请将其重新排列后变为:\nL0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → … 不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。\n思路 # 寻找链表中心结点 + 翻转链表 + 合并链表\n代码 # 暴力解 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode getTail(ListNode head) { ListNode ptr = head; while (ptr.next != null \u0026amp;\u0026amp; ptr.next.next != null) ptr = ptr.next; ListNode tail = ptr.next; ptr.next = null; return tail; } public void reorderList(ListNode head) { if (head == null || head.next == null) return; ListNode tail = getTail(head); tail.next = head.next; head.next = tail; reorderList(tail.next); } } 寻找链表中间结点+反转链表+合并链表 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { /** 寻找链表中心结点 */ public ListNode findMiddle(ListNode head) { ListNode sentinel = new ListNode(-1, head); ListNode slow = sentinel, fast = sentinel; while (fast != null \u0026amp;\u0026amp; fast.next != null) { slow = slow.next; fast = fast.next.next; } ListNode result = slow.next; slow.next = null; return result; } /** 反转链表 */ public ListNode reverseList(ListNode head) { ListNode prev = null, cur = head, temp = head.next; while (cur != null) { cur.next = prev; prev = cur; cur = temp; if (temp != null) temp = temp.next; } return prev; } /** 合并链表 */ public void reorderList(ListNode head) { if (head == null || head.next == null) return; ListNode middle = findMiddle(head); ListNode tail = reverseList(middle); ListNode ptr1 = head, ptr2 = tail; while (ptr1 != null \u0026amp;\u0026amp; ptr2 != null) { ListNode newPtr1 = ptr1.next, newPtr2 = ptr2.next; ptr1.next = ptr2; ptr2.next = newPtr1; ptr1 = newPtr1; ptr2 = newPtr2; } } } 致谢 # 灵茶山艾府\n"},{"id":30,"href":"/docs/codes/0100-to-0199/0146.-LRU-Cache/","title":"0146. Lru Cache","section":"0100 to 0199","content":" 146. LRU Cache # 题目 # 设计并实现一个满足 LRU(最近最少使用)缓存 约束的数据结构。\n实现 LRUCache 类:\nLRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存 int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value;如果不存在,则向缓存中插入该组 key-value,如果插入操作导致关键字数量超过 capacity,则应该逐出最久未使用的关键字。 函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。 思路 # 使用 双向链表 结合 哈希表 实现 LRU Cache 数据结构。\n代码 # class LRUCache { private class ListNode { int key; int val; public ListNode prev; public ListNode next; ListNode (int key, int val, ListNode prev, ListNode next) { this.key = key; this.val = val; this.prev = prev; this.next = next; } } int size; int capacity; HashMap\u0026lt;Integer, ListNode\u0026gt; map; ListNode sentinel; public LRUCache(int capacity) { this.size = 0; this.capacity = capacity; this.map = new HashMap\u0026lt;Integer, ListNode\u0026gt;(); this.sentinel = new ListNode(-1, -1, null, null); this.sentinel.next = this.sentinel.prev = this.sentinel; } public int get(int key) { if (this.map.containsKey(key) == false) return -1; ListNode ptr = this.map.get(key); moveToHead(ptr); return ptr.val; } public void put(int key, int value) { if (this.map.containsKey(key) == false) { if (this.size == capacity) removeTail(); else this.size += 1; ListNode ptr = new ListNode(key, value, this.sentinel, this.sentinel.next); this.sentinel.next = ptr; ptr.next.prev = ptr; this.map.put(key, ptr); } else { ListNode ptr = this.map.get(key); ptr.val = value; moveToHead(ptr); } } public void moveToHead(ListNode ptr) { ptr.prev.next = ptr.next; ptr.next.prev = ptr.prev; ptr.next = this.sentinel.next; ptr.prev = this.sentinel; ptr.next.prev = ptr; ptr.prev.next = ptr; } public void removeTail() { ListNode tail = this.sentinel.prev; this.sentinel.prev = tail.prev; this.prev.next = this.sentinel; this.map.remove(tail.key); /** Is HashMap.remove() O(1) ? */ } } 致谢 # 宫水三叶 labuladong "},{"id":31,"href":"/docs/codes/0100-to-0199/0147.-Insertion-Sort-List/","title":"0147. Insertion Sort List","section":"0100 to 0199","content":" 147. Insertion Sort List # 题目 # 给定单个链表的头 head ,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。\n插入排序 算法的步骤:\n插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。 每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。 重复直到所有输入数据插入完为止。 思路 # 代码 # class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode insertSortList(ListNode head) { ListNode sentinel = new ListNode(-1, head); /** 设置 preserve 指向已排序链表的尾结点,每次新处理的结点为 preserve.next */ ListNode preserve = sentinel, toInsert = preserve.next; while (toInsert != null) { ListNode ptr = sentinel; while (ptr != preserve \u0026amp;\u0026amp; ptr.next.val \u0026lt;= toInsert.val) ptr = ptr.next; if (ptr == preserve) { preserve = preserve.next; toInsert = preserve.next; } else { preserve.next = toInsert.next; toInsert.next = ptr.next; ptr.next = toInsert; toInsert = preserve.next; } } return sentinel.next; } } "},{"id":32,"href":"/docs/codes/0100-to-0199/0160.-Intersection-of-Two-Linked-List/","title":"0160. Intersection of Two Linked List","section":"0100 to 0199","content":" 160. Intersection of Two Linked Lists # 题目 # 给定两个单链表的头节点headA和headB,找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回null。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode(int x) { val = x; next = null; } } public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { if (headA == null || headB == null) return null; ListNode ptrA = headA, ptrB = headB; while (ptrA != ptrB) { ptrA = ptrA.next; ptrB = ptrB.next; if (ptrA == null \u0026amp;\u0026amp; ptrB == null) return null; else if (ptrA == null) ptrA = headB; else if (ptrB == null) ptrB = headA; } return ptrA; } } "},{"id":33,"href":"/docs/codes/0200-to-0299/0203.-Remove-Linked-List-Elements/","title":"0203. Remove Linked List Elements","section":"0200 to 0299","content":" 203. Remove Linked List Elements # 题目 # 给定链表头节点head和一个整数val,删除链表中所有满足Node.val == val的节点,并返回新的头节点。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode removeElements(ListNode head, int val) { if (head == null) return null; if (head.val == val) return removeElements(head.next, val); else { head.next = removeElements(head.next, val); return head; } } } "},{"id":34,"href":"/docs/codes/0200-to-0299/0206.-Reverse-Linked-List/","title":"0206. Reverse Linked List","section":"0200 to 0299","content":" 206. Reverse Linked List # 题目 # 给定单链表头节点head,反转并返回反转后的链表。\n思路 # 代码 # 递归 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode reverseList(ListNode head) { if (head == null || head.next == null) return head; ListNode newHead = reverseList(head.next); head.next.next = head; head.next = null; return newHead; } } 迭代 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode reverseList(ListNode head) { ListNode prev = null, cur = head, next = head.next; while (cur != null) { cur.next = prev; prev = cur; cur = next; if (next != null) next = next.next; } return prev; } } "},{"id":35,"href":"/docs/codes/0200-to-0299/0209.-Minimum-Size-Subarray-Sum/","title":"0209. Minimum Size Subarray Sum","section":"0200 to 0299","content":" 209. Minimum Size Subarray Sum # 题目 # 给定一个含有n个正整数的数组和一个正整数target。找出该数组中满足其和\u0026gt;=target的长度最小的连续子数组,并返回其长度。如果不存在符合条件的子数组,返回0。\n思路 # 代码 # class Solution { public int minSubArrayLen(int target, int[] nums) { if (nums == null) return 0; int left=0, right=0, len=0, cumSum=0; while (left \u0026lt;= right \u0026amp;\u0026amp; right \u0026lt; nums.length) { curSum += nums[right]; if (curSum \u0026gt;= target) { if (len == 0 || len \u0026gt; right-left+1) len = right-left+1; curSum -= nums[left]; left += 1; curSum -= nums[right]; } else right += 1; } return len; } } "},{"id":36,"href":"/docs/codes/0200-to-0299/0234.-Palindrome-Linked-List/","title":"0234. Palindrome Linked List","section":"0200 to 0299","content":" 234. Palindrome Linked List # 题目 # 给定单链表的头节点head,判断该链表是否为回文链表。\n考虑使用O(n)时间复杂度和O(1)空间复杂度解决此题。\n思路 # 分割、翻转 # 使用快慢指针找到链表中心节点。 如果链表长度为偶,则fast.next == null时,slow指向链表前半部分的最后一个节点。 如果链表长度为奇,则fast == null时,slow指向链表的轴节点。 使用迭代的方式以O(1)空间复杂度翻转链表的后半部分。 判断链表是否为回文链表。 将后半部分链表恢复原状,避免对链表的破坏。 返回结果。 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode locateMiddle(ListNode head) { ListNode slow = head, fast = head.next; while (fast != null \u0026amp;\u0026amp; fast.next != null) { slow = slow.next; fast = fast.next.next; } return slow; } public ListNode reverseList(ListNode head) { ListNode prev = null, cur = head, next = head.next; while (cur != null) { cur.next = prev; prev = cur; cur = next; if (next != null) next = next.next; } return prev; } public boolean compareList(ListNode ptrA, ListNode ptrB) { while (ptrA != null \u0026amp;\u0026amp; ptrB != null) { if (ptrA.val != ptrB.val) return false; ptrA = ptrA.next; ptrB = ptrB.next; } return true; } public boolean isPalindrome(ListNode head) { if (head == null || head.next == null) return true; ListNode middle = locateMiddle(head); ListNode tail = reverseList(middle.next); boolean isConsistent = compareList(head, tail); reverseList(middle.next); return isConsistent; } } "},{"id":37,"href":"/docs/codes/0200-to-0299/0237.-Delete-Nodes-in-A-Linked-List/","title":"0237. Delete Nodes in a Linked List","section":"0200 to 0299","content":" 237. Delete Node in A Linked List # 题目 # 有一个单链表的head,想要删除它的一个节点node。\n给定需要删除的节点node,并且无法访问第一个节点head。\n链表所有值都是唯一的,且给定的节点node不是链表中的最后一个节点。\n删除节点的意思是指:\n给定节点的值不应该存在于链表中。 链表中的节点数应该减少1。 node前面所有值的顺序相同。 node后面所有值的顺序相同。 思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public void deleteNode(ListNode node) { node.val = node.next.val; node.next = node.next.next; } } "},{"id":38,"href":"/docs/codes/0200-to-0299/0242.-Valid-Anagram/","title":"0242. Valid Anagram","section":"0200 to 0299","content":" 237. Valid Anagram # 题目 # 给定两个字符串 s 和 t,编写一个函数来判断 t 是否是 s 的字母异位词。\n若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。\n思路 # 代码 # public Solution { public boolean isAnagram(String s, String t) { if (s.length() != t.length()) return false; Map\u0026lt;Character, Integer\u0026gt; sMap = new HashMap\u0026lt;\u0026gt;(); Map\u0026lt;Character, Integer\u0026gt; tMap = new HashMap\u0026lt;\u0026gt;(); for (int i=0; i\u0026lt;s.length(); i++) { char ch = s.charAt(i); int times = sMap.containsKey(ch) == false ? 0 : sMap.get(ch); sMap.put(ch, times + 1); } for (int i=0; i\u0026lt;t.length(); i++) { char ch = t.charAt(i); if (sMap.containsKey(ch) == false) return false; if (sMap.get(ch) == 0) return false; sMap.put(ch, sMap.get(ch) - 1); } return true; } } "},{"id":39,"href":"/docs/codes/0300-to-0399/0328.-Odd-Even-Linked-List/","title":"0328. Odd Even Linked List","section":"0300 to 0399","content":" 328. Odd Even Linked List # 题目 # 给定单链表头节点head,将所有索引为奇数的节点和所有索引为偶数的节点分别组合在一起,然后返回重新排序的链表。\n第一个节点的索引被认为是奇数,第二个节点的索引被认为是偶数,以此类推。\n偶数组和奇数组内部的相对顺序应该与输入时保持一致。\n需要在O(1)的额外空间复杂度和O(n)的时间复杂度下解决这个问题。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode oddEvenList(ListNode head) { if (head == null || head.next == null) return head; ListNode Odd = head, Even = head.next; ListNode ptrOdd = Odd, ptrEven = Even; while (ptrEven != null \u0026amp;\u0026amp; ptrEven.next != null) { ptrOdd.next = ptrEven.next; ptrOdd = ptrOdd.next; ptrEven.next = ptrOdd.next; ptrEven = ptrEven.next; } ptrOdd.next = Even; return Odd; } } "},{"id":40,"href":"/docs/codes/0300-to-0399/0349.-Intersection-of-Two-Arrays/","title":"0349. Intersection of Two Arrays","section":"0300 to 0399","content":" 349. Intersection of Two Arrays # 题目 # 给定两个数组 nums1 和 nums2,返回 它们的交集。输出结果中的每个元素一定是 唯一 的。不考虑输出结果的顺序。\n思路 # 代码 # class Solution { public int[] intersection(int[] nums1, int[] nums2) { Set\u0026lt;Integer\u0026gt; set = new HashSet\u0026lt;\u0026gt;(); for (int num: nums1) set.add(num); List\u0026lt;Integer\u0026gt; list = new ArrayList\u0026lt;\u0026gt;(); for (int num: nums2) { if (set.contains(num) == true) { list.add(num); set.remove(num); } } int[] result = new int[list.size()]; for (int i=0; i\u0026lt;list.size(); i++) result[i] = list.get(i); return result; } } "},{"id":41,"href":"/docs/codes/0300-to-0399/0355.-Design-Twitter/","title":"0355. Design Twitter","section":"0300 to 0399","content":" 355. Design Twitter # 题目 # 设计一个简化版的推特,让用户实现发送推文,关注/取消关注其他用户,能够看见关注人(包括自己)的最近 10 条推文。\n实现 Twitter 类:\nTwitter() 初始化简易版推特对象 void postTweet(int userId, int tweetId) 根据给定的 tweetId 和 userId 创建一条新推文。每次调用此函数都会使用一个不同的 tweetId。 List\u0026lt;Integer\u0026gt; getNewsFeed(int userId) 检索当前用户新闻推送中最近 10 条推文的 ID。新闻推送中的每一项都必须是由用户关注的人或者是用户自己发布的推文。推文必须 按照时间顺序由最近到最远排序。 void follow(int followerId, int followeeId) ID 为 followerId 的用户开始关注 ID 为 followeeId 的用户。 void unfollow(int followerId, int followeeId) ID 为 followerId 的用户不再关注 ID 为 followeeId 的用户。 思路 # 哈希表 存储用户的关注列表。 单链表 存储用户的推文链表。 优先级队列 实现按时间戳排序的推文链表的合并。 大顶堆 实现最近 N 条推文的获取。 代码 # class Twitter { private class ListNode implements Comparable\u0026lt;ListNode\u0026gt; { public int timestamp; public int tweetId; public ListNode next; ListNode(int timestamp, int tweetId, ListNode next) { this.timestamp = timestamp; this.tweetId = tweetId; this.next = next; } public int compareTo(ListNode other) { return other.timestamp - this.timestamp; } } private class User { public int userId; public ListNode tweets; public Set\u0026lt;User\u0026gt; following; User(int userId, ListNode tweets) { this.userId = userId; this.tweets = tweets; this.following = new HashSet\u0026lt;\u0026gt;(); this.following.add(this); } } private Map\u0026lt;Integer, User\u0026gt; map; private int timestamp; public void postTweet(int userId, int tweetId) { if (this.map.containsKey(userId) == false) this.map.put(userId, new User(userId, null)); User user = this.map.get(userId); this.timestamp += 1; user.tweets = new ListNode(this.timestamp, tweetId, user.tweets); } public List\u0026lt;Integer\u0026gt; getNewsFeed(int userId) { List\u0026lt;Integer\u0026gt; newsFeed = new ArrayList\u0026lt;\u0026gt;(); PriorityQueue\u0026lt;ListNode\u0026gt; queue = new PriorityQueue\u0026lt;\u0026gt;(); if (this.map.containsKey(userId) == false) this.map.put(userId, new User(userId, null)); for (User player: this.map.get(userId).following) { if (player.tweets != null) { queue.offer(player.tweets); } } while (newsFeed.size() \u0026lt; 10 \u0026amp;\u0026amp; queue.size() != 0) { ListNode tweets = queue.poll(); newsFeed.add(tweets.tweetId); if (tweets.next != null) queue.offer(tweets.next); } return newsFeed; } public void follow(int followerId, int followeeId) { if (this.map.containsKey(followerId) == false) this.map.put(followerId, new User(followerId, null)); if (this.map.containsKey(followeeId) == false) this.map.put(followeeId, new User(followeeId, null)); User follower = this.map.get(followerId), followee = this.map.get(followeeId); follower.following.add(followee); } public void unfollow(int followerId, int followeeId) { User follower = this.map.get(followerId), followee = this.map.get(followeeId); follower.following.remove(followee); } } 致谢 # liweiwei\n"},{"id":42,"href":"/docs/codes/0300-to-0399/0369.-Plus-One-Linked-List/","title":"0369. Plus One Linked List","section":"0300 to 0399","content":" 369. Plus One Linked List # 题目 # 给定一个用 链表 表示的非负整数,然后将这个整数加一。\n最高位有效数字位于链表的首尾 head。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public int helper(ListNode head, int carry) { if (head.next == null) { int result = (head.val + carry) / 10; head.val = (head.val + carry) % 10; return result; } else { int newCarry = helper(head.next, carry); int result = (head.val + newCarry) / 10; head.val = (head.val + newCarry) % 10; return result; } } public ListNode plusOne(ListNode head) { int carry = helper(head, 1); if (carry == 0) return head; else return new ListNode(carry ,head); } } "},{"id":43,"href":"/docs/codes/0300-to-0399/0379.-Design-Phone-Directory/","title":"0379. Design Phone Directory","section":"0300 to 0399","content":" 379. Design Phone Directory # 题目 # 设计一个电话目录管理系统,令其支持以下功能:\nget: 分配给用户一个未被使用的电话号码,获取失败时返回 -1 check:检查指定的电话号码是否被使用 release:释放掉一个电话号码,使其能够重新被分配 思路 # 代码 # class PhoneDirectory { private class ListNode { int val; ListNode prev; ListNode next; ListNode(int val, ListNode prev, ListNode next) { this.val = val; this.prev = prev; this.next = next; } } private ListNode sentinel; private Map\u0026lt;Integer, ListNode\u0026gt; map; /** 记录电话号码 number 是否被分配 */ public PhoneDirectory(int maxNumbers) { this.sentinel = new ListNode(-1, null, null); this.sentinel.prev = this.sentinel.next = this.sentinel; for (int i=0; i\u0026lt;maxNumbers; i++) { this.sentinel.prev = new ListNode(i, this.sentinel.prev, this.sentinel); this.sentinel.prev.prev.next = this.sentinel.prev; } this.map = new HashMap\u0026lt;\u0026gt;(); } public int get() { if (this.sentinel.next == this.sentinel) return -1; int result = this.sentinel.next.val; this.map.put(this.sentinel.next.val, this.sentinel.next); this.sentinel.next = this.sentinel.next.next; this.sentinel.next.prev = this.sentinel; return result; } public boolean check(int number) { return this.map.containsKey(number) == false; } public void release(int number) { if (this.map.containsKey(number) == false) return; ListNode ptr = this.map.get(number); ptr.prev = this.sentinel; ptr.next = this.sentinel.next; this.sentinel.next = ptr; ptr.next.prev = ptr; this.map.remove(number); } } "},{"id":44,"href":"/docs/codes/0300-to-0399/0382.-Linked-List-Random-Node/","title":"0382. Linked List Random Node","section":"0300 to 0399","content":" 382. Linked List Random Node # 题目 # 给定单链表,随机选择链表的一个节点,并返回相应的节点值。每个节点被选中的概率一样。\n考虑处理以下情形:\n链表非常大且长度未知 使用O(1)的额外空间复杂度 思路 # 使用 蓄水池抽样算法 以O(n)的时间复杂度和O(1)的空间复杂度解决此问题。\n代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { private Random rand; private ListNode sentinel; public Solution(ListNode head) { this.rand = new Random(); this.sentinel = new ListNode(-1, head); } public int getRandom() { ListNode ptr = this.sentinel; int size = 0, result = -1; while (ptr.next != null) { ptr = ptr.next; size += 1; if (this.rand.nextInt(0, size) == 0) result = ptr.val; } return result; } } 致谢 # 小学生都能看懂的蓄水池抽样算法 - @迷路的小画家 - 哔哩哔哩 蓄水池抽样算法 - @五点七边 - 哔哩哔哩 宫水三叶 Random sampling with a reservoir "},{"id":45,"href":"/docs/codes/0400-to-0499/0430.-Flatten-a-Multilevel-Doubly-Linked-List/","title":"0430. Flatten a Multilevel Doubly Linked List","section":"0400 to 0499","content":" 430. Flatten a Multilevel Doubly Linked List # 题目 # 给定一个双链表,各节点有一个 next 指针、一个 prev 指针和一个的 child 指针 。这个 child 指针 可能指向一个单独的双向链表,也包含这些特殊的节点。这些子列表可以有一个或多个自己的子列表,从而构成 多层数据结构 。\n给定链表的头节点 head ,将链表 扁平化 ,使所有节点都出现在单层双链表中。让 curr 是一个带有子列表的节点。子列表中的节点应该出现在扁平化列表中的 curr 之后 和 curr.next 之前 。\n返回 扁平列表的 head 。列表中的节点必须将其 所有 子指针设置为 null 。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public Node getTail(Node head) { if (head.child == null \u0026amp;\u0026amp; head.next == null) return head; else if (head.child != null \u0026amp;\u0026amp; head.next != null) { Node tail = getTail(head.child); tail.next = head.next; head.next.prev = tail; head.next = head.child; head.child.prev = head; head.child = null; return getTail(head.next.next); } else if (head.child != null \u0026amp;\u0026amp; head.next == null) { head.next = head.child; head.child.prev = head; head.child = null; return getTail(head.next); } else return getTail(head.next); } public Node flatten(Node head) { if (head == null) return null; getTail(head); return head; } } "},{"id":46,"href":"/docs/codes/0400-to-0499/0432.-All-O1-Data-Structure/","title":"0432. All O(1) Data Structure","section":"0400 to 0499","content":" 432. All O(1) Data Structure # 题目 # 设计一个用于存储字符串计数的数据结构,并能够返回计数最小和最大的字符串。\n实现 AllOne 类:\nAllOne() 初始化数据结构的对象。 inc(String key) 字符串 key 的计数增加 1 。如果数据结构中尚不存在 key ,那么插入计数为 1 的 key 。 dec(String key) 字符串 key 的计数减少 1 。如果 key 的计数在减少后为 0 ,那么需要将这个 key 从数据结构中删除。测试用例保证:在减少计数前,key 存在于数据结构中。 getMaxKey() 返回任意一个计数最大的字符串。如果没有元素存在,返回一个空字符串 \u0026quot;\u0026quot; 。 getMinKey() 返回任意一个计数最小的字符串。如果没有元素存在,返回一个空字符串 \u0026quot;\u0026quot; 。 **注意:**每个函数都应当满足 O(1) 平均时间复杂度。\n思路 # 采用 双向链表 + 哈希表 的方式实现。 链表结点记录 频率 以及 该频率对应的字符串集合,以 Max \u0026lt;\u0026ndash;\u0026gt; Min 的顺序存储。 HashSet 可以在 O(1) 的时间复杂度内实现 add 和 remove 操作。 代码 # class AllOne { private class ListNode { public int count; public Set\u0026lt;String\u0026gt; collection; public ListNode prev; public ListNode next; ListNode(int count, ListNode prev, ListNode next) { this.count = count; this.collection = new HashSet\u0026lt;\u0026gt;(); this.prev = prev; this.next = next; } } private ListNode sentinel; private Map\u0026lt;String, ListNode\u0026gt; map; public AllOne() { this.sentinel = new ListNode(-1, null, null); this.sentinel.prev = this.sentinel.next = this.sentinel; this.map = new HashMap\u0026lt;\u0026gt;(); } /** Max \u0026lt;--\u0026gt; Min */ public void inc(String key) { if (this.map.containsKey(key) == false) { if (this.sentinel.prev.count != 1) { this.sentinel.prev = new ListNode(1, this.sentinel.prev, this.sentinel); this.sentinel.prev.prev.next = this.sentinel.prev; } this.sentinel.prev.collection.add(key); this.map.put(key, this.sentinel.prev); return; } ListNode ptr = this.map.get(key); ptr.collection.remove(key); /** 将 key 提升到频率为 (ptr.count + 1) 的结点集合里 */ if (ptr.prev.count != ptr.count + 1) { ptr.prev = new ListNode(ptr.count + 1, ptr.prev, ptr); ptr.prev.prev.next = ptr.prev; } ptr.prev.collection.add(key); this.map.put(key, ptr.prev); /** 若 collection 为空,表明当前不存在频率为 ptr.count 的字符串,移除 ptr 结点 */ clean(ptr); } /** Max \u0026lt;--\u0026gt; Min */ public void dec(String key) { ListNode ptr = this.map.get(key); ptr.collection.remove(key); if (ptr.count -1 == 0) { this.map.remove(key); clean(ptr); return; } /** 将 key 下放到频率为 ptr.count-1 的结点集合里 */ if (ptr.next.count != ptr.count -1) { ptr.next = new ListNode(ptr.count-1, ptr, ptr.next); ptr.next.next.prev = ptr.next; } ptr.next.collection.add(key); this.map.put(key, ptr.next); /** 若 collection 为空,表明当前不存在频率为 ptr.count 的字符串,移除 ptr 结点 */ clean(ptr); } public void clean(ListNode ptr) { if (ptr.collection.size() == 0) { ptr.prev.next = ptr.next; ptr.next.prev = ptr.prev; } } public String getMaxKey() { ListNode ptr = this.sentinel.next; for(String str: ptr.collection) return str; return \u0026#34;\u0026#34;; } public String getMinKey() { ListNode ptr = this.sentinel.prev; for(String str: ptr.collection) return str; return \u0026#34;\u0026#34;; } } 致谢 # 宫水三叶\n"},{"id":47,"href":"/docs/codes/0400-to-0499/0445.-Add-Two-Numbers-ii/","title":"0445. Add Two Numbers Ii","section":"0400 to 0499","content":" 445. Add Two Numbers II # 题目 # 给定两个非空链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public int helper(ListNode l1, ListNode l2) { if (l1.next == null \u0026amp;\u0026amp; l2.next == null) { int carry = (l1.val + l2.val) / 10; l1.val = (l1.val + l2.val) % 10; return carry; } else { int carry = helper(l1.next, l2.next); int newCarry = (l1.val + l2.val + carry) / 10; l1.val = (l1.val + l2.val + carry) % 10; /** note */ return newCarry; } } public int addToList(ListNode head, ListNode tail, int carry) { if (head == tail) { int newCarry = (head.val + carry) / 10; head.val = (head.val + carry) % 10; return newCarry; } else { int newCarry = addToList(head.next, tail, carry); int result = (head.val + newCarry) / 10; head.val = (head.val + newCarry) % 10; return result; } } public ListNode addTwoNumbers(ListNode l1, ListNode l2) { if (l1 == null) return l2; if (l2 == null) return l1; int lenOfL1 = 0, lenOfL2 = 0; ListNode ptrOfL1 = l1, ptrOfL2 = l2; while(ptrOfL1 != null) { lenOfL1 += 1; ptrOfL1 = ptrOfL1.next; } while(ptrOfL2 != null) { lenOfL2 += 1; ptrOfL2 = ptrOfL2.next; } if (lenOfL1 == lenOfL2) { int carry = helper(l1, l2); if (carry == 0) return l1; else return new ListNode(carry, l1); } else if (lenOfL1 \u0026gt; lenOfL2) { ListNode beforeAlign = l1; for (int i=0; i \u0026lt; lenOfL1 - lenOfL2 - 1; i++) beforeAlign = beforeAlign.next; int carry = helper(beforeAlign.next, l2); if (carry == 0) return l1; else { int newCarry = addToList(l1, beforeAlign, carry); if (newCarry == 0) return l1; else return new ListNode(newCarry, l1); } } else { ListNode beforeAlign = l2; for (int i=0; i \u0026lt; lenOfL2 - lenOfL1 - 1; i++) beforeAlign = beforeAlign.next; int carry = helper(beforeAlign.next, l1); if (carry == 0) return l2; else { int newCarry = addToList(l2, beforeAlign, carry); int (newCarry == 0) return l2; else return new ListNode(newCarry, l2); } } } } "},{"id":48,"href":"/docs/codes/0400-to-0499/0460.-LFU-Cache/","title":"0460. Lfu Cache","section":"0400 to 0499","content":" 460. LFU Cache # 题目 # 为 最不经常使用(LFU)缓存算法设计并实现数据结构。\n实现 LFUCache 类:\nLFUCache(int capacity) - 用数据结构的容量 capacity 初始化对象 int get(int key) - 如果键 key 存在于缓存中,则获取键的值,否则返回 -1 。 void put(int key, int value) - 如果键 key 已存在,则变更其值;如果键不存在,请插入键值对。当缓存达到其容量 capacity 时,则应该在插入新项之前,移除最不经常使用的项。在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,应该去除 最近最久未使用 的键。 为了确定最不常使用的键,可以为缓存中的每个键维护一个 使用计数器 。使用计数最小的键是最久未使用的键。\n当一个键首次插入到缓存中时,它的使用计数器被设置为 1 (由于 put 操作)。对缓存中的键执行 get 或 put 操作,使用计数器的值将会递增。\n函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。\n思路 # 代码 # class LFUCache { private class ListNode { public int key; public int frequency; public int val; public ListNode prev; public ListNode next; ListNode(int key, int value, ListNode prev, ListNode next) { this.key = key; this.val = value; this.frequency = 0; this.prev = prev; this.next = next; } } private int size; private int capacity; private ListNode sentinel; private Map\u0026lt;Integer, ListNode\u0026gt; keyMap; private Map\u0026lt;Integer, ListNode\u0026gt; freqMap; public int get(int key) { if (this.capacity == 0) return -1; if (this.keyMap.containsKey(key) == false) return -1; ListNode node = this.keyMap.get(key); /** 由于 get 操作,node.frequency 递增,修订 freqMap */ refresh(node); return node.val; } public void put(int key, int value) { if (this.keyMap.containsKey(key) == true) { ListNode node = this.keyMap.get(key); node.val = value; refresh(node); return; } else if (this.size == this.capacity) { /** 在 keyMap 中移除 LRU 结点 */ this.keyMap.remove(this.sentinel.prev.key); /** 若 LRU 结点是 LRU.frequency 的独苗,则在freqMap中移除 LRU 结点 */ if (this.sentinel.prev == this.freqMap.get(this.sentinel.prev.frequency)) this.freqMap.remove(this.sentinel.prev.frequency); /** 移除 LRU 结点 */ this.sentinel.prev = this.sentinel.prev.prev; this.sentinel.prev.next = this.sentinel; } ListNode node = new ListNode(key, value, this.sentinel.prev, this.sentinel); node.prev.next = node; node.next.prev = node; this.keyMap.put(key, node); refresh(node); if (this.size \u0026lt; this.capacity) this.size += 1; } public void refresh(ListNode node) { /** 变更 node.frequency 在 freqMap 中的映射 */ if (node.frequency != 0) { ListNode frontier = this.freqMap.get(node.frequency); if (node == frontier \u0026amp;\u0026amp; node.frequency == node.next.frequency) this.freqMap.put(node.frequency, node.next); else if (node == frontier \u0026amp;\u0026amp; node.frequency != node.next.frequency) this.freqMap.remove(node.frequency); else { node.prev.next = node.next; node.next.prev = node.prev; node.prev = frontier.prev; node.next = frontier; node.prev.next = node; node.next.prev = node; } } /** 变更 node.frequency + 1 在 freqMap 中的映射 */ node.frequency += 1; if (this.freqMap.containsKey(node.frequency) == true) { ListNode frontier = this.freqMap.get(node.frequency); node.prev.next = node.next; node.next.prev = node.prev; node.prev = frontier.prev; node.next = frontier; node.prev.next = node; node.next.prev = node; } this.freqMap.put(node.frequency, node); } } "},{"id":49,"href":"/docs/codes/0600-to-0699/0622.-Design-Circular-Queue/","title":"0622. Design Circular Queue","section":"0600 to 0699","content":" 622. Design Circular Queue # 题目 # 设计循环队列。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。\n循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。\n你的实现应该支持如下操作:\nMyCircularQueue(k): 构造器,设置队列长度为 k 。 Front: 从队首获取元素。如果队列为空,返回 -1 。 Rear: 获取队尾元素。如果队列为空,返回 -1 。 enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。 deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。 isEmpty(): 检查循环队列是否为空。 isFull(): 检查循环队列是否已满。 思路 # 基于链表的实现较为简单,而基于数组的实现相对复杂。\n代码 # class MyCircularQueue { private class ListNode { int val; ListNode prev; ListNode next; ListNode (int val, ListNode prev, ListNode next) { this.val = val; this.prev = prev; this.next = next; } } private int size; private int capacity; ListNode sentinel; public MyCircularQueue(int k) { this.capacity = k; this.size = 0; this.sentinel = new ListNode(-1, null, null); this.sentinel.prev = this.sentinel.next = this.sentinel; } public boolean enQueue(int value) { if (isFull() == true) return false; this.sentinel.prev = new ListNode(value, this.sentinel.prev, this.sentinel); this.sentinel.prev.prev.next = this.sentinel.prev; this.size += 1; return true; } public boolean deQueue() { if (isEmpty() == true) return false; this.sentinel.next = this.sentinel.next.next; this.sentinel.next.prev = this.sentinel; this.size -= 1; return true; } public int Front() { if (isEmpty() == true) return -1; else return this.sentinel.next.val; } public int Rear() { if (isEmpty() == true) return -1; else return this.sentinel.prev.val; } public boolean isEmpty() { return this.size == 0; } public boolean isFull() { return this.size == capacity; } } "},{"id":50,"href":"/docs/codes/0600-to-0699/0641.-Design-Circular-Deque/","title":"0641. Design Circular Deque","section":"0600 to 0699","content":" 641. Design Circular Deque # 题目 # 设计实现双端队列。\n实现 MyCircularDeque 类:\nMyCircularDeque(int k) :构造函数,双端队列最大为 k 。 boolean insertFront():将一个元素添加到双端队列头部。 如果操作成功返回 true ,否则返回 false 。 boolean insertLast() :将一个元素添加到双端队列尾部。如果操作成功返回 true ,否则返回 false 。 boolean deleteFront() :从双端队列头部删除一个元素。 如果操作成功返回 true ,否则返回 false 。 boolean deleteLast() :从双端队列尾部删除一个元素。如果操作成功返回 true ,否则返回 false 。 int getFront() ):从双端队列头部获得一个元素。如果双端队列为空,返回 -1 。 int getRear() :获得双端队列的最后一个元素。 如果双端队列为空,返回 -1 。 boolean isEmpty() :若双端队列为空,则返回 true ,否则返回 false 。 boolean isFull() :若双端队列满了,则返回 true ,否则返回 false 。 思路 # 代码 # class MyCircularDeque { private class ListNode { public int val; public ListNode prev; public ListNode next; ListNode (int value, ListNode prev, ListNode next) { this.val = value; this.prev = prev; this.next = next; } } private int size; private int capacity; private ListNode sentinel; public MyCircularDeque(int k) { this.size = 0; this.capacity = k; this.sentinel = new ListNode(-1, null, null); this.sentinel.prev = this.sentinel.next = this.sentinel; } public boolean insertFront(int value) { if (this.isFull()) return false; this.sentinel.next = new ListNode(value, this.sentinel, this.sentinel.next); this.sentinel.next.next.prev = this.sentinel.next; this.size += 1; return true; } public boolean insertLast(int value) { if (this.isFull()) return false; this.sentinel.prev = new ListNode(value, this.sentinel.prev, this.sentinel); this.sentinel.prev.prev.next = this.sentinel.prev; this.size += 1; return true; } public boolean deleteFront() { if (this.isEmpty()) return false; this.sentinel.next = this.sentinel.next.next; this.sentinel.next.prev = this.sentinel; this.size -= 1; return true; } public boolean deleteLast() { if (this.isEmpty()) return false; this.sentinel.prev = this.sentinel.prev.prev; this.sentinel.prev.next = this.sentinel; this.size -= 1; return true; } public int getFront() { if (this.isEmpty()) return -1; return this.sentinel.next.val; } public int getRear() { if (this.isEmpty()) return -1; return this.sentinel.prev.val; } public boolean isEmpty() { return this.size == 0; } public boolean isFull() { return this.size == this.capacity; } } "},{"id":51,"href":"/docs/codes/0700-to-0799/0704.-Binary-Search/","title":"0704. Binary Search","section":"0700 to 0799","content":" 704. Binary Search # 题目 # 给定一个n个元素有序的升序整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下标,否则返回-1。\n思路 # 保持consistency不变量。\n代码 # class Solution { public int search(int[] nums, int target) { int left = 0, right = nums.length; while (left \u0026lt; right) { int medium = left + (right - left) / 2; if (nums[medium] == target) return medium; else if (nums[medium] \u0026gt; target) right = medium; else left = medium + 1; } return -1; } } "},{"id":52,"href":"/docs/codes/0700-to-0799/0707.-Design-Linked-List/","title":"0707. Design Linked List","section":"0700 to 0799","content":" 707. Design Linked List # 题目 # 设计链表的实现。可以选择使用单链表或双链表。\n在链表类中实现这些功能:\nget(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。 addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。 addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。 addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。 deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。 思路 # 代码 # public class ListNode { public ListNode prev; public ListNode next; public int val; public ListNode(ListNode prev, ListNode next, int val) { this.prev = prev; this.next = next; this.val = val; } } class MyLinkedList { private ListNode sentinel; private int size; public MyLinkedList() { this.sentinel = new ListNode(null, null, -1); this.sentinel.prev = this.sentinel; this.sentinel.next = this.sentinel; this.size = 0; } public int get(int index) { if (index \u0026lt; 0 || index \u0026gt;= this.size) return -1; ListNode ptr = this.sentinel.next; for (int i=0; i\u0026lt;index; i++) ptr = ptr.next; return ptr.val; } public void addAtHead(int val) { this.sentinel.next = new ListNode(this.sentinel, this.sentinel.next, val); this.sentinel.next.next.prev = this.sentinel.next; this.size += 1; } public void addAtTail(int val) { this.sentinel.prev = new ListNode(this.sentinel.prev, this.sentinel, val); this.sentinel.prev.prev.next = this.sentinel.pre; this.size += 1; } public void addAtIndex(int index, int val) { if (index \u0026lt;= 0) this.addAtHead(val); else if (index == this.size) this.addAtTail(val); else if (index \u0026gt; 0 \u0026amp;\u0026amp; index \u0026lt; this.size) { ListNode ptr = this.sentinel; for (int i=0; i\u0026lt;index; i++) ptr = ptr.next; ptr.next = new ListNode(ptr, ptr.next, val); ptr.next.next.prev = ptr.next; this.size += 1; } } public void deleteAtIndex(int index) { if (index == 0) { this.sentinel.next = this.sentinel.next.next; this.sentinel.next.prev = this.sentinel; this.size -= 1; } else if (index == this.size - 1) { this.sentinel.prev = this.sentinel.prev.prev; this.sentinel.prev.next = this.sentinel; this.size -= 1; } else if (index \u0026gt; 0 \u0026amp;\u0026amp; index \u0026lt; this.size - 1) { ListNode ptr = this.sentinel; for (int i=0; i\u0026lt;index; i++) ptr = ptr.next; ptr.next = ptr.next.next; ptr.next.prev = ptr; this.size -= 1; } } } "},{"id":53,"href":"/docs/codes/0700-to-0799/0708.-Insert-into-a-Sorted-Circular-Linked-List/","title":"0708. Insert Into a Sorted Circular Linked List","section":"0700 to 0799","content":" 708. Insert into a Sorted Circular Linked List # 题目 # 给定 循环单调非递减列表 中的一个点,写一个函数向这个列表中插入一个新元素 interval,使这个列表仍然是循环非降序的。\n给定的可以是这个列表中任意一个顶点的指针,并不一定是这个列表中最小元素的指针。\n如果有多个满足条件的插入位置,可以选择任意一个位置插入心得值,插入后整个列表仍然保持有序。\n如果列表为空(给定的节点是 null),需要创建一个循环有序列表并返回这个节点。否则,返回原先给定的节点。\n思路 # 代码 # class Node { public int val; public Node next; public Node() {} public Node(int _val) { val = _val; } public Node(int _val, Node _next) { val = _val; next = _next; } } class Solution { public boolean canInsert (Node head, int insertVal) { if (head.val == insertVal) return true; if (head.val \u0026lt; insertVal \u0026amp;\u0026amp; insertVal \u0026lt; head.next.val) return true; if (head.val \u0026gt; head.next.val \u0026amp;\u0026amp; head.val \u0026lt; insertVal) return true; if (head.val \u0026gt; head.next.val \u0026amp;\u0026amp; insertVal \u0026lt; head.next.val) return true; return false; } public Node insert(Node head, int insertVal) { if (head == null) { Node ring = new Node(insertVal); ring.next = ring; return ring; } else { Node ptr = head; while (ptr.next != head \u0026amp;\u0026amp; canInsert(ptr, insertVal) == false) ptr = ptr.next; ptr.next = new Node(insertVal, ptr.next); return head; } } "},{"id":54,"href":"/docs/codes/0700-to-0799/0716.-Max-Stack/","title":"0716. Max Stack","section":"0700 to 0799","content":" 716. Max Stack # 题目 # 设计一个最大栈数据结构,既支持栈操作,又支持查找栈中最大元素。\n实现 MaxStack 类:\nMaxStack() 初始化栈对象 void push(int x) 将元素 x 压入栈中 int pop() 移除栈顶元素并返回这个元素 int top() 返回栈顶元素,无需移除 int peekMax() 检索并返回栈中最大元素,无需移除 int popMax() 检索并返回栈中最大元素,并将其移除。如果有多个最大元素,移除 最靠近栈顶 的那个 思路 # Explicit Better Than Implicit 代码 # class MaxStack { private class ListNode implements Comparable\u0026lt;ListNode\u0026gt; { public int index; public int val; public ListNode prev; public ListNode next; ListNode(int index, int val, ListNode prev, ListNode next) { this.index = index; this.val = val; this.prev = prev; this.next = next; } public int compareTo(ListNode other) { if (this.val == other.val) return other.index - this.index; return other.val - this.val; } } private ListNode sentinel; private PriorityQueue\u0026lt;ListNode\u0026gt; queue; private int index; public MaxStack() { this.sentinel = new ListNode(-1, -1, null, null); this.sentinel.prev = this.sentinel.next = this.sentinel; this.queue = new PriorityQueue\u0026lt;\u0026gt;(); this.index = 0; } public void push(int x) { this.index += 1; this.sentinel.next = new ListNode(this.index, x, this.sentinel, this.sentinel.next); this.sentinel.next.next.prev = this.sentinel.next; this.queue.offer(this.sentinel.next); } public int pop() { int result = this.sentinel.next.val; this.queue.remove(this.sentinel.next); this.sentinel.next = this.sentinel.next.next; this.sentinel.next.prev = this.sentinel; return result; } public int top() { return this.sentinel.next.val; } public int peekMax() { return this.queue.peek().val; } public int popMax() { ListNode ptr = this.queue.poll(); ptr.prev.next = ptr.next; ptr.next.prev = ptr.prev; return ptr.val; } } "},{"id":55,"href":"/docs/codes/0700-to-0799/0725.-Split-Linked-List-in-Parts/","title":"0725. Split Linked List in Parts","section":"0700 to 0799","content":" 725. Split Linked List in Parts # 题目 # 给定一个头结点为head的单链表和一个整数k,设计一个算法将链表分隔为k个连续的部分。\n每部分的长度应该尽可能相等:任意两部分的长度差距不能超过1,这可能会导致有些部分为null。\n这k个部分应该按照在链表中出现的顺序排列,并且排在前面的部分的长度应不小于排在后面的长度。\n返回一个由上述k部分组成的数组。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode[] splitListToParts(ListNode head, int k) { /** 1. 确定链表长度 length */ ListNode ptr = head; int length = 0; while (ptr != null) { length += 1; ptr = ptr.next; } /** 2. 声明指针数组 */ ListNode[] result = new ListNode[k]; /** 3. 对链表长度小于k的情况进行讨论 */ if (length \u0026lt; k) { ptr = head; for (int i=0; i\u0026lt;k; i++) { result[i] = ptr; if (ptr != null) { ListNode tmp = ptr.next; ptr.next = null; ptr = tmp; } } } /** 4. 对链表长度大于k的情况进行讨论 */ else { ptr = head; int interval = length / k; for (int i=0; i\u0026lt;length % k; i++) { result[i] = ptr; for (int j=0; j\u0026lt;interval+1; j++) { if (j == interval) { ListNode tmp = ptr.next; ptr.next = null; ptr = tmp; } else ptr = ptr.next; } } for ( int i = length % k; i \u0026lt; k; i++) { result[i] = ptr; for (int j=0; j\u0026lt;interval; j++) { if (j == interval - 1) { ListNode tmp = ptr.next; ptr.next = null; ptr = tmp; } else ptr = ptr.next; } } } return result; } } "},{"id":56,"href":"/docs/codes/0800-to-0899/0817.-Linked-List-Components/","title":"0817. Linked List Components","section":"0800 to 0899","content":" 0817. Linked List Components # 题目 # 给定链表头结点 head,该链表上的每个结点都有一个 唯一的整型值。同时给定列表 nums,该列表是上述链表中整型值的一个子集。\n返回列表 nums 中组件的个数,这里对组件的定义为:链表中一段最长连续结点的值(该值必须在列表 nums 中)构成的集合。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public int numComponents(ListNode head, int[] nums) { Set\u0026lt;Integer\u0026gt; set = new HashSet\u0026lt;\u0026gt;(); for(int x: nums) set.add(x); boolean flag = false; int num = 0; ListNode ptr = head; while (ptr != null) { if (set.contains(ptr.val) == true) { if (flag == false) flag = true; } else { if (flag == true) num += 1; flag = false; } ptr = ptr.next; } if (flag == ture) num += 1; return num; } } "},{"id":57,"href":"/docs/codes/0800-to-0899/0876.-Middle-of-the-Linked-List/","title":"0876. Middle of the Linked List","section":"0800 to 0899","content":" 876. Middle of the Linked List # 题目 # 给定一个头结点为head的非空单链表,返回链表的中间结点。\n如果有两个中间结点,则返回第二个中间结点。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode middleNode(ListNode head) { ListNode sentinel = new ListNode(-1, head); ListNode middle = sentinel, fast = sentinel; while (fast != null \u0026amp;\u0026amp; fast.next != null) { middle = middle.next; fast = fast.next.next; } if (fast != null) middle = middle.next; return middle; } } "},{"id":58,"href":"/docs/codes/0900-to-0999/0977.-Squares-of-A-Sorted-Array/","title":"0977. Squares of a Sorted Array","section":"0900 to 0999","content":" 977. Squares of A Sorted Array # 题目 # 给定按 非递减顺序 排序的整型数组 nums,返回 每个数字的平方 组成的新数组,要求新数组也按 非递减顺序 排序。\n思路 # 代码 # class Solution { public int[] sortedSquares(int[] nums) { if (nums == null) return null; int sz = nums.length; int[] result = new int[sz]; if (nums[0] \u0026gt;= 0) for (int i=0; i\u0026lt;sz; i++) result[i] = nums[i] * nums[i]; else if (nums[sz-1] \u0026lt;= 0) for (int i=sz-1; i\u0026gt;=0; i--) result[sz-1] = nums[i] * nums[i]; else { int left=-1, right=nums.length; index=0; while (nums[left+1] \u0026lt; 0) left+=1; right = left + 1; while (left \u0026gt;= 0 \u0026amp;\u0026amp; right \u0026lt; sz) { if (-nums[left] \u0026lt; nums[right]) { result[index] = nums[left] * nums[left]; left -= 1; } else { result[index] = nums[right] * nums[right]; right += 1; } index += 1; } while (index \u0026lt; sz) { if (left \u0026gt;= 0) { result[index] = nums[left] * nums[left]; left -= 1; } else { result[index] = nums[right] * nums[right]; right += 1; } } } return result; } } "},{"id":59,"href":"/docs/codes/1000-to-1099/1019.-Next-Greater-Node-in-Linked-List/","title":"1019. Next Greater Node in Linked List","section":"1000 to 1099","content":" 1019. Next Grater Node in Linked List # 题目 # 给定一个长度为n的链表head\n对于链表中的每个节点,查找下一个更大节点的值。即,对于每个节点,找到它旁边的第一个节点的值,这个节点的值严格大于它的值。\n返回一个整数数组answer,其中answer[i]是第i个节点(从1开始)的下一个更大节点的值。如果第i个节点没有下一个更大的节点,设置answer[i] = 0。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public int[] nextLargerNodes(ListNode head) { /** 1. 统计链表长度 */ int length = 0; ListNode ptr = head; while (ptr != null) { length += 1; ptr = ptr.next; } /** 2. 将链表转化为数组 */ int[] valueArray = new int[length]; ptr = head; for (int i=0; i\u0026lt;length; i++) { valueArray[i] = ptr.val; ptr = ptr.next; } /** 3. 创建索引数组,存储当前元素下一个更大节点的下标值 */ int[] indexArray = new int[length]; /** 4. 创建结果数组,存储当前元素下一个更大节点的元素值 */ int[] answer = new int[length]; for (int i=length-1; i\u0026gt;=0; i--) { if (i == length-1) { indexArray[i] = -1; answer[i] = 0; } else if (valueArray[i] \u0026lt; valueArray[i+1]) { indexArray[i] = i+1; answer[i] = valueArray[i+1]; } else { /** 当前节点不小于紧邻节点,借助索引数组寻找潜在的更大节点 */ int index = indexArray[i+1]; while (index != -1 \u0026amp;\u0026amp; valueArray[i] \u0026gt;= valueArray[index]) index = indexArray[index]; if (index == -1) { indexArray[i] = -1; answer[i] = 0; } else { indexArray[i] = index; answer[i] = valueArray[index]; } } } return answer; } } "},{"id":60,"href":"/docs/codes/1100-to-1199/1171.-Remove-Zero-Sum-Consecutive-Nodes-from-Linked-List/","title":"1171. Remove Zero Sum Consecutive Nodes From Linked List","section":"1100 to 1199","content":" 1171. Remove Zero Sum Consecutive Nodes from Linked List # 题目 # 给定链表头节点 head ,反复删去链表中由 总和 值为 0 的连续节点组成的序列,直到不存在这样的序列为止。\n删除完毕后,返回最终结果链表的头节点。\n思路 # 考察第 k 个链表结点,判断其是否位于某个 零子序列 中,只需通过检查第 k-1 个结点的前缀和在 \u0026gt;=k 结点处是否再次出现。 可以通过两次遍历链表,借助 HashMap 实现这一需求 第一趟遍历,计算每个结点的前缀和,并构建前缀和与最远结点的映射关系 第二趟遍历,从哨兵结点开始,从映射中查找当前前缀和对应的结点,若找到则移除之间的结点。 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode removeZeroSumSublists(ListNode head) { ListNode sentinel = new ListNode(0, head); Map\u0026lt;Integer, ListNode\u0026gt; map = new HashMap\u0026lt;\u0026gt;(); map.put(0, sentinel); int sum = 0; for (ListNode ptr = head; ptr != null; ptr = ptr.next) { sum += ptr.val; map.put(sum, ptr); } sum = 0; for (ListNode ptr = sentinel; ptr != null; ptr = ptr.next) { sum += ptr.val; if (map.containsKey(sum) == true) ptr.next = map.get(sum).next); } return sentinel.next; } } 致谢 # shane\n"},{"id":61,"href":"/docs/codes/1200-to-1299/1265.-Print-Immutable-Linked-List-in-Reverse/","title":"1265. Print Immutable Linked List in Reverse","section":"1200 to 1299","content":" 1265. Print Immutable Linked List in Reverse # 题目 # 给定一个不可变的链表,使用下列接口逆序打印每个节点的值:\nImmutableListNode: 描述不可变链表的接口,链表的头节点已给出。 使用以下 API 来访问此链表:\nImmutableListNode.printValue():打印当前节点的值。 ImmutableListNode.getNext():返回下一个节点。 思路 # 代码 # class Solution { public void printLinkedListInReverse(ImmutableListNode head) { if (head == null) return; printLinkedListInReverse(head.getNext()); head.printValue(); } } "},{"id":62,"href":"/docs/codes/1200-to-1299/1290.-Convert-Binary-Number-in-A-Linked-List-to-Integer/","title":"1290. Convert Binary Number in a Linked List to Integer","section":"1200 to 1299","content":" 1290. Convert Binary Number in A Linked List to Integer # 题目 # 给定单链表头节点head,已知此链表是一个整数数字的二进制表示形式,链表中每个节点的值非0即1。返回链表所表示数字的十进制值。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode reverseList(ListNode head) { ListNode prev = null, cur = head, next = head.next; while(cur != null) { cur.next = prev; prev = cur; cur = next; if (next != null) next = next.next; } return prev; } public int getDecimalValue(ListNode head) { ListNode newHead = reverseList(head); int decimal = 0, digit = 0; ListNode ptr = newHead; while (ptr != null) { decimal += Math.pow(2, digit) * ptr.val; digit += 1; ptr = ptr.next; } reverseList(newHead); return decimal; } } "},{"id":63,"href":"/docs/codes/1400-to-1499/1472.-Design-Browser-History/","title":"1472. Design Browser History","section":"1400 to 1499","content":" 1472. Design Browser History # 题目 # 现有一个只支持单个标签页的 浏览器, 最开始浏览的网页是 homepage,可以访问其他的网站 url,也可以在浏览器中后退 steps 步或前进 steps 步。\n设计实现 BrowserHistory 类:\nBrowserHistory(string homepage) 用 homepage 初始化浏览器类。 void visit(string url) 从当前页面跳转访问 url 对应的页面。执行此操作会把浏览历史前进的记录全部删除。 string back(int steps) 在浏览历史中后退 steps 步。如果只能在浏览历史中后退至多 x 步且 steps \u0026gt; x,那么只后退 x 步。请返回后退至多 steps 步以后的 url。 string forward(int steps) 在浏览历史中前进 steps 步。如果只能在浏览历史中前进至多 x 步且 steps \u0026gt; x,那么只前进 x 步。请返回前进至多 steps 步以后的 url。 思路 # 借助双向链表实现。 注意 visit 操作执行后会将浏览历史前进的记录全部删除。 代码 # class BrowserHistory { private class ListNode { public String url; public ListNode prev; public ListNode next; ListNode(String url, ListNode prev, ListNode next) { this.url = url; this.prev = prev; this.next = next; } } private ListNode head; private ListNode ptr; public BrowserHistory(String homepage) { this.head = new ListNode(homepage, null, null); this.head.next = this.head.prev = this.head; this.ptr = head; } public void visit(String url) { this.ptr.next = new ListNode(url, this.ptr, this.head); this.head.prev = this.ptr.next; this.ptr = this.ptr.next; } public String back(int steps) { for (int i=0; i\u0026lt;steps; i++) { if (this.ptr == this.head) return this.ptr.url; else this.ptr = this.ptr.prev; } return this.ptr.url; } public String forward(int steps) { for (int i=0; i\u0026lt;steps; i++) { if (this.ptr.next == this.head) return this.ptr.url; else this.ptr = this.ptr.next; } return this.ptr.url; } } "},{"id":64,"href":"/docs/codes/1400-to-1499/1474.-Delete-N-Nodes-After-M-Nodes-of-A-Linked-List/","title":"1474. Delete N Nodes After M Nodes of a Linked List","section":"1400 to 1499","content":" 1472. Design Browser History # 题目 # 给定链表头结点 head 和两个整数 m 和 n,遍历该链表并按照如下方式删除结点:\n开始时以头结点作为当前结点 保留以当前结点开始的前 m 个结点 删除接下来的 n 个结点 重复步骤 2 和 3,直到到达链表结尾 在删除了指定结点之后,返回修改过后的链表头结点。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } LIstNOde(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode deleteNodes(ListNode head, int m, int n) { ListNode sentinel = new ListNode(-1, head); ListNode ptr = sentinel; while (ptr.next != null) { /** 保留前 m 个结点 */ for (int i=0; i\u0026lt;m; i++) { if (ptr.next == null) return head; ptr = ptr.next; } /** 删除后 n 个结点 */ for (int i=0; i\u0026lt;n; i++) { if (ptr.next == null) return head; ptr.next = ptr.next.next; } } return head; } } "},{"id":65,"href":"/docs/codes/1600-to-1699/1634.-Add-Two-Polynomials-Represented-as-Linked-Lists/","title":"1634. Add Two Polynomials Represented as Linked Lists","section":"1600 to 1699","content":" 1634. Add Two Polynomials Represented as Linked Lists # 题目 # 多项式链表是一种特殊形式的链表,每个结点表示多项式的一项。\n每个结点有三个属性:\ncoefficient: 该项的系数 power:该项的指数 next:指向下一个结点的指针,如果当前结点为链表的最后一个结点则为 null 多项式链表是标准形式的,即多项式 严格 按指数 power 的递减顺序排列。系数 coefficient 为 0 的项需要省略。\n给定两个多项式链表的头结点 poly1 和 poly2,返回它们的和的头结点。\n思路 # 代码 # class PolyNode { int coefficient, power; PolyNode next = null; PolyNode() {} PolyNode(int x, int y) { this.coefficient = x; this.power = y; } PolyNode(int x, int y, PolyNode next) { this.coefficient = x; this.power = y; this.next = next; } } class Solution { public PolyNode mergePoly(PolyNode poly1, PolyNode poly2) { if (poly1 == null \u0026amp;\u0026amp; poly2 == null) return null; if (poly1 == null) return poly2; if (poly2 == null) return poly1; if (poly1.power == poly2.power) { poly1.coefficient += poly2.coefficient; if (poly1.coefficient == 0) return mergePoly(poly1.next, poly2.next); poly1.next = mergePoly(poly1.next, poly2.next); return poly1; } else if (poly1.power \u0026gt; poly2.power) { poly1.next = mergePoly(poly1.next, poly2); return poly1; } else { poly2.next = mergePoly(poly1, poly2.next); return poly2; } } } "},{"id":66,"href":"/docs/codes/1600-to-1699/1669.-Merge-in-Between-Linked-Lists/","title":"1669. Merge in Between Linked Lists","section":"1600 to 1699","content":" 1669. Merge in Between Linked Lists # 题目 # 给定两个链表list1和list2,它们包含的元素分别为n个和m个。\n将list1中下标从a到b的全部节点都删除,并将list2接在被删除节点的位置。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode mergeInBetween(ListNode list1, int a, int b, ListNode list2) { ListNode ptrA = list1, ptrB = list1; for (int i=0; i\u0026lt;a-1; i++) ptrA = ptrA.next; for (int i=0; i\u0026lt;b; i++) ptrB = ptrB.next; ListNode rear = list2; while (rear.next != null) rear = rear.next; ptrA.next = list2; rear.next = ptrB.next; return list1; } } "},{"id":67,"href":"/docs/codes/1600-to-1699/1670.-Design-Front-Middle-Back-Queue/","title":"1670. Design Front Middle Back Queue","section":"1600 to 1699","content":" 1670. Design Front Middle Back Queue # 题目 # 请你设计一个队列,支持在前,中,后三个位置的 push 和 pop 操作。\n请你完成 FrontMiddleBack 类:\nFrontMiddleBack() 初始化队列。 void pushFront(int val) 将 val 添加到队列的 最前面 。 void pushMiddle(int val) 将 val 添加到队列的 正中间 。 void pushBack(int val) 将 val 添加到队里的 最后面 。 int popFront() 将 最前面 的元素从队列中删除并返回值,如果删除之前队列为空,那么返回 -1 。 int popMiddle() 将 正中间 的元素从队列中删除并返回值,如果删除之前队列为空,那么返回 -1 。 int popBack() 将 最后面 的元素从队列中删除并返回值,如果删除之前队列为空,那么返回 -1 。 思路 # 代码 # class FrontMiddleBackQueue { private class ListNode { int val; ListNode prev; ListNode next; ListNode(int value, ListNode prev, ListNode next) { this.val = value; this.prev = prev; this.next = next; } } private int size; ListNode sentinel; ListNode middle; public FrontMiddleBackQueue() { this.size = 0; this.sentinel = new ListNode(-1, null, null); this.sentinel.prev = this.sentinel.next = this.sentinel; this.middle = this.sentinel; } public void pushFront(int val) { this.sentinel.next = new ListNode(val, this.sentinel, this.sentinel.next); this.sentinel.next.next.prev = this.sentinel.next; /** 对于 pushFront 操作: * 若插入前链表长度为偶数,则 middle 指针不移动 * 若插入前链表长度为奇数,则 middle 指针需向前移动一位 */ if (this.size == 0) this.middle = this.sentinel.next; else if (this.size % 2 == 1) this.middle = this.middle.prev; this.size += 1; } public void pushMiddle(int val) { if (this.size == 0) { this.sentinel.next = new ListNode(val, this.sentinel, this.sentinel); this.sentinel.prev = this.sentinel.next; this.middle = this.sentinel.next; this.size += 1; } else if (this.size % 2 == 1) { this.middle.prev.next = new ListNode(val, this.middle.prev, this.middle); this.middle.prev = this.middle.prev.next; this.middle = this.middle.prev; this.size += 1; } else { this.middle.next = new ListNode(val, this.middle, this.middle.next); this.middle.next.next.prev = this.middle.next; this.middle = this.middle.next; this.size += 1; } } public void pushBack(int val) { this.sentinel.prev = new ListNode(val, this.sentinel.prev, this.sentinel); this.sentinel.prev.prev.next = this.sentinel.prev; /** 对于 pushBack 操作: * 若插入前链表长度为偶数,则 middle 指针需向后移动一位 * 若插入前链表长度为奇数,则 middle 指针不移动 */ if (this.size == 0) this.middle = this.sentinel.next; else if (this.size % 2 == 0) this.middle = this.middle.next; this.size += 1; } public int popFront() { if (this.size == 0) return -1; int result = this.sentinel.next.val; this.sentinel.next = this.sentinel.next.next; this.sentinel.next.prev = this.sentinel; if (this.size == 1) this.middle = this.sentinel; else if (this.size % 2 == 0) this.middle = this.middle.next; this.size -= 1; return result; } public int popMiddle() { if (this.size == 0) return -1; int result = this.middle.val; this.middle.prev.next = this.middle.next; this.middle.next.prev = this.middle.prev; if (this.size == 1) this.middle = this.sentinel; else if (this.size % 2 == 0) this.middle = this.middle.next; else if (this.size % 2 == 1) this.middle = this.middle.prev; this.size -= 1; return result; } public int popBack() { if (this.size == 0) return -1; int result = this.sentinel.prev.val; this.sentinel.prev = this.sentinel.prev.prev; this.sentinel.prev.next = this.sentinel; if (this.size == 1) this.middle = this.sentinel; else if (this.size % 2 == 1) this.middle = this.middle.prev; this.size -= 1; return result; } } "},{"id":68,"href":"/docs/codes/1700-to-1799/1721.-Swapping-Nodes-in-A-Linked-List/","title":"1721. Swapping Nodes in a Linked List","section":"1700 to 1799","content":" 1721. Swapping Nodes in A Linked List # 题目 # 给定链表头节点head和一个整数k\n交换链表正数第k个节点和倒数第k个节点的值后,返回链表的头节点(链表从1开始索引)\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution{ public ListNode locateForward(ListNode head, int k) { ListNode sentinel = new ListNode(-1, head); ListNode ptr = sentinel; for (int i=0; i\u0026lt;k; i++) ptr = ptr.next; return ptr; } public ListNode locateBackward(ListNode head, int k) { ListNode sentinel = new ListNode(-1, head); ListNode slow = sentinel, fast = sentinel; for (int i=0; i\u0026lt;k; i++) fast = fast.next; while (fast != null) { slow = slow.next; fast = fast.next; } return slow; } public ListNode swapNodes(ListNode head, int k) { ListNode forwardK = locateForward(head, k); ListNode backwardK = locateBackward(head, k); int tmp = forwardK.val; forwardK.val = backwardK.val; backwardK.val = tmp; return head; } } "},{"id":69,"href":"/docs/codes/1800-to-1899/1836.-Remove-Duplicates-From-an-Unsorted-Linked-List/","title":"1836. Remove Duplicates From an Unsorted Linked List","section":"1800 to 1899","content":" 1836. Remove Duplicates from An Unsorted Linked List # 题目 # 给定链表头节点 head,找到链表中所有出现 多于一次 的元素,并删除这些元素所在的节点。返回删除后的链表。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode deleteDuplicatesUnsorted(ListNode head) { Map\u0026lt;Integer, Integer\u0026gt; map = new HashMap\u0026lt;\u0026gt;(); ListNode ptr = head; while (ptr != null) { int times = map.containsKey(ptr.val) == true ? map.get(ptr.val) : 0; map.put(ptr.val, times + 1); ptr = ptr.next; } ListNode sentinel = new ListNode(-1, head); ptr = sentinel; while (ptr.next != null) { if (map.get(ptr.next.val) \u0026gt; 1) ptr.next = ptr.next.next; else ptr = ptr.next; } return sentinel.next; } } "},{"id":70,"href":"/docs/codes/2000-to-2099/2046.-Sort-Linked-List-Already-Sorted-Using-Absolute-Values/","title":"2046. Sort Linked List Already Sorted Using Absolute Values","section":"2000 to 2099","content":" 2046. Sort Linked List Already Sorted Using absolute Values # 题目 # 给定链表头结点 head,该链表根据结点的 绝对值 进行 升序 排序,返回重新根据 结点的值 进行 升序 排序的链表。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode sortLinkedList(ListNode head) { ListNode sentinel = new ListNode(-1, head); ListNode ptr = head; while (ptr != null \u0026amp;\u0026amp; ptr.next != null) { if (ptr.next.val \u0026lt;= sentinel.next.val) { ListNode node = ptr.next; ptr.next = node.next; node.next = sentinel.next; sentinel.next = node; } else ptr = ptr.next; } return sentinel.next; } } "},{"id":71,"href":"/docs/codes/2000-to-2099/2058.-Find-the-Minimum-and-Maximum-Number-of-Nodes-Between-Critical-Points/","title":"2058. Find the Minimum and Maximum Number of Nodes Between Critical Points","section":"2000 to 2099","content":" 2058. Find the Minimum and Maximum Number of Nodes Between Critical Points # 题目 # 链表中的 临界点 定义为一个 局部极大值点 或 局部极小值点 。\n如果当前节点的值 严格大于 前一个节点和后一个节点,那么这个节点就是一个 局部极大值点 。\n如果当前节点的值 严格小于 前一个节点和后一个节点,那么这个节点就是一个 局部极小值点 。\n注意:节点只有在同时存在前一个节点和后一个节点的情况下,才能成为一个 局部极大值点 / 极小值点 。\n给你一个链表 head ,返回一个长度为 2 的数组 [minDistance, maxDistance] ,其中 minDistance 是任意两个不同临界点之间的最小距离,maxDistance 是任意两个不同临界点之间的最大距离。如果临界点少于两个,则返回 [-1,-1] 。\n思路 # 在第一个节点存在的情况下,每遇到一个新的临界点,maxDistance 在原有基础上递增距离,minDistance 重新计算。 maxDistance 是所有临界点分段的距离之和。 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { boolean isLocalMaximum(ListNode ptr) { return ptr.next.val \u0026gt; ptr.val \u0026amp;\u0026amp; ptr.next.val \u0026gt; ptr.next.next.val; } boolean isLocalMinimum(ListNode ptr) { return ptr.next.val \u0026lt; ptr.val \u0026amp;\u0026amp; ptr.next.val \u0026lt; ptr.next.next.val; } public int[] nodesBetweenCriticalPoints(ListNode head) { int[] distanceMinMax = new int[]{-1, -1}; int step = 0; ListNode ptr = head, mark = null; while (ptr.next.next != null) { if (isLocalMaximum(ptr) == null || isLocalMinimum(ptr) == null) { if (mark != null) { if (distanceMinMax[0] == -1) distanceMinMax[0] = distanceMinMax[1] = step + 1; else { distanceMinMax[0] = (step + 1) \u0026lt; distanceMinMax[0] ? step + 1: distanceMinMax[0]; distanceMinMax[1] += step + 1; } } ptr = mark = ptr.next; step = 0; } else { ptr = ptr.next; step += 1; } } return distanceMinMax; } } "},{"id":72,"href":"/docs/codes/2000-to-2099/2074.-Reverse-Nodes-in-Even-Length-Groups/","title":"2074. Reverse Nodes in Even Length Groups","section":"2000 to 2099","content":" 2074. Reverse Nodes in Even Length Groups # 题目 # 给定链表头结点 head。\n链表中的结点按照 按顺序 划分为若干 非空 组。这些非空组的长度构成一个自然数序列 {1, 2, 3, 4, ...}。一个组的 长度 就是组中分配到的结点数目。换言之:\n结点 1 分配给第一组 结点 2 分配给第二组 结点 4、5、6 分配给第三组,以此类推 注意,最后一组的长度可能小于或等于 1 + 倒数第二组的长度。\n反转 每个 偶数长度 组中的结点,并返回修改后链表的头结点 head。\n思路 # 代码 # class Solution { public void reverseList(ListNode beforeHead, ListNode tail) { /** (beforeHead, tail] 要求 beforeHead != tail */ if (beforeHead == tail) return; ListNode afterTail = tail.next; ListNode prev = afterTail, cur = beforeHead.next, temp = cur.next; while (cur != afterTail) { cur.next = prev; prev = cur; cur = temp; if (temp != afterTail) temp = temp.next; } beforeHead.next = tail; } public ListNode reverseEvenLengthGroups(ListNode head) { ListNode sentinel = new ListNode(-1, head); /** interval 标识正在考察那一段链表结点 */ int interval = 1; /** 确定待考察区间的前驱结点 beforeHead 和 尾结点 tail */ ListNode beforeHead = sentinel, tail = sentinel; /** 若链表发生翻转,tail 指向的结点不再位于区间末尾。新的尾结点是翻转前的 before.next 结点,用 ptr 变量暂存这一结点。*/ ListNode ptr = null; /** 若 tail 遇到了 null 指针,结束遍历 */ while (tail != null) { /** 统计区间的实际长度 */ int length = 0; /** 覆盖了 tail 处于正常结点和空结点两种情况 */ for (int i=0; i\u0026lt;interval \u0026amp;\u0026amp; tail.next != null; i++) { tail = tail.next; length += 1; } /** 判断是否要翻转区间 (beforeHead, tail],如果是则执行 */ ptr = beforeHead.next; if (length % 2 == 0) reverseList(beforeHead, tail); /** 继续考虑下一段区间 */ beforeHead = tail = length % 2 == 0 ? ptr : tail; interval += 1; } return head; } } "},{"id":73,"href":"/docs/codes/2000-to-2099/2095.-Delete-the-Middle-Node-of-A-Linked-List/","title":"2095. Delete the Middle Node of a Linked List","section":"2000 to 2099","content":" 2095. Delete the Middle Node of A Linked List # 题目 # 给定链表头节点head,删除链表的中间节点,并返回修改后的链表头节点head。\n长度为 n 链表的中间节点是从头数起第 ⌊n / 2⌋ 个节点(下标从 0 开始),其中 ⌊x⌋ 表示小于或等于 x 的最大整数。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode deleteMiddle(ListNode head) { if (head == null) return null; ListNode sentinel = new ListNode(-1, head); ListNode middle = sentinel, fast = sentinel; while (fast != null \u0026amp;\u0026amp; fast.next != null) { middle = middle.next; fast = fast.next.next; } if (fast != null) middle = middle.next; ListNode ptr = sentinel; while (ptr.next != middle) ptr = ptr.next; ptr.next = middle.next; return sentinel.next; } } "},{"id":74,"href":"/docs/codes/2100-to-2199/2130.-Maximum-Twin-Sum-of-A-Linked-List/","title":"2130. Maximum Twin Sum of a Linked List","section":"2100 to 2199","content":" 2130. Maximum Twin Sum of A Linked List # 题目 # 在一个大小为 n 且 n 为 偶数 的链表中,对于 0 \u0026lt;= i \u0026lt;= (n / 2) - 1 的 i ,第 i 个节点(下标从 0 开始)的孪生节点为第 (n-1-i) 个节点 。\n比方说,n = 4 那么节点 0 是节点 3 的孪生节点,节点 1 是节点 2 的孪生节点。这是长度为 n = 4 的链表中所有的孪生节点。 孪生和 定义为一个节点和它孪生节点两者值之和。\n给你一个长度为偶数的链表的头节点 head ,请你返回链表的 最大孪生和 。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } lass Solution { /** 定位链表中心节点 */ public ListNode findMiddle(ListNode head) { ListNode sentinel = new ListNode(-1, head); ListNode slow = sentinel, fast = sentinel; while (fast != null \u0026amp;\u0026amp; fast.next != null) { slow = slow.next; fast = fast.next.next; } ListNode result = slow.next; slow.next = null; return result; } /** 翻转链表 */ public ListNode reverseList(ListNode head) { ListNode prev = null, cur = head, temp = head.next; while (cur != null) { cur.next = prev; prev = cur; cur = temp; if (temp != null) temp = temp.next; } return prev; } public int pairSum(ListNode head) { ListNode middle = findMiddle(head); ListNode tail = reverseList(middle); int result = head.val + tail.val; ListNode ptrHead = head.next, ptrTail = tail.next; while (ptrHead != null \u0026amp;\u0026amp; ptrTail != null) { if (ptrHead.val + ptrTail.val \u0026gt; result) result = ptrHead.val + ptrTail.val; ptrHead = ptrHead.next; ptrTail = ptrTail.next; } return result; } } "},{"id":75,"href":"/docs/codes/2100-to-2199/2181.-Merge-Nodes-in-Between-Zeros/","title":"2181. Merge Nodes in Between Zeros","section":"2100 to 2199","content":" 2181. Merge Nodes in Between Zeros # 题目 # 给定链表头节点 head ,该链表包含由 0 分隔开的一连串整数。链表的 开端 和 末尾 的节点都满足 Node.val == 0 。\n对于每两个相邻的 0 ,之间的所有节点合并为一个节点,其值是所有已合并节点的值之和。然后将所有 0 移除,修改后的链表不应该含有任何 0 。\n返回修改后链表的头节点 head 。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode mergeNodes(ListNode head) { ListNode sentinel = new ListNode(-1, head); ListNode ptr = sentinel; while (ptr != null) { if (ptr.next.val == 0) { ptr.next = ptr.next.next; ptr = ptr.next; } else { ptr.val += ptr.next.val; ptr.next = ptr.next.next; } } return sentinel.next; } } "},{"id":76,"href":"/docs/codes/2200-to-2299/2296.-Design-A-Text-Editor/","title":"2296. Design a Text Editor","section":"2200 to 2299","content":" 2296. Design A Text Editor # 题目 # 请设计一个带光标的文本编辑器,它可以实现以下功能:\n添加:在光标处添加文本。 删除:在光标处删除文本。 移动:将光标往左或往右移动。 当删除文本时,只有光标左边的字符会被删除。光标会留在文本内,即任何时候 0 \u0026lt;= cursor.position \u0026lt;= currentText.length 都成立。\n请实现 TextEditor 类:\nTextEditor() 用空文本初始化对象。 void addText(String text) 将 text 添加到光标所在位置。添加完后光标在 text 的右边。 int deleteText(int k) 删除光标左边 k 个字符。返回实际删除的字符数目。 String cursorLeft(int k) 将光标向左移动 k 次。返回移动后光标左边 min(10, len) 个字符,其中 len 是光标左边的字符数目。 String cursorRight(int k) 将光标向右移动 k 次。返回移动后光标左边 min(10, len) 个字符,其中 len 是光标左边的字符数目。 思路 # 代码 # class TextEditor { private class ListNode { public char character; public ListNode prev; public ListNode next; ListNode (char character, ListNode prev, ListNode next) { this.character = character; this.prev = prev; this.next = next; } } private ListNode sentinel; /** cursor 是光标指针,(ptr, cursor] 指示 cursor 在内的左侧字符,长度不大于 threshold */ private ListNode ptr; private ListNode cursor; private int windowSize; private int threshold; public TextEditor() { this.windowSize = 0; this.threshold = 10; this.sentinel = new ListNode(\u0026#39;s\u0026#39;, null, null); this.sentinel.prev = this.sentinel.next = this.sentinel; this.ptr = this.sentinel; this.cursor = this.sentinel; } public void addText(String text) { for (int i=0; i\u0026lt;text.length(); i++) { this.cursor.next = new ListNode(text.charAt(i), this.cursor, this.cursor.next); this.cursor.next.next.prev = this.cursor.next; this.cursor = this.cursor.next; if (this.windowSize == this.threshold) this.ptr = this.ptr.next; else this.windowSize += 1; } } public int deleteText(int k) { int result = 0; for (int i=0; i\u0026lt;k \u0026amp; this.windowSize \u0026gt; 0; i++) { this.cursor = this.cursor.prev; this.cursor.next = this.cursor.next.next; this.cursor.next.prev = this.cursor; if (this.ptr == this.sentinel) this.windowSize -= 1; else this.ptr = this.ptr.prev; result += 1; } return result; } public String cursorLeft(int k) { String result = \u0026#34;\u0026#34;; for (int i=0; i\u0026lt;k \u0026amp;\u0026amp; this.windowSize \u0026gt; 0; i++) { this.cursor = this.cursor.prev; if (this.ptr == this.sentinel) this.windowSize -= 1; else this.ptr = this.ptr.prev; } ListNode node = this.ptr; while (node != this.cursor) { node = node.next; result += String.valueOf(node.character); } return result; } public String cursorRight(int k) { String result = \u0026#34;\u0026#34;; for (int i=0; i\u0026lt;k \u0026amp;\u0026amp; this.cursor.next != this.sentinel; i++) { this.cursor = this.cursor.next; if (this.windowSize == this.threshold) this.ptr = this.ptr.next; else this.windowSize += 1; } ListNode node = this.ptr; while (node != this.cursor) { node = node.next; result += String.valueOf(node.character); } return result; } } "},{"id":77,"href":"/docs/codes/2300-to-2399/2326.-Spiral-Matrix-IV/","title":"2326. Spiral Matrix Iv","section":"2300 to 2399","content":" 2326. Spiral Matrix IV # 题目 # 给定两个整数 m 和 n,表示矩阵的维数。\n另外给定一个整数链表的头节点 head。\n生成并返回一个大小为 m x n 的螺旋矩阵,矩阵包含链表中的所有整数。链表中的整数从矩阵左上角开始、顺时针按螺旋顺序填充。如果还存在剩余的空格,则用 -1 填充。\n思路 # 代码 # class Solution { public int getValue(ListNode[] ptr) { if (ptr[0] == null) return -1; int value = ptr[0].val; ptr[0] = ptr[0].next; return value; } public void helper(int[][] result, int top, int bottom, int left, int right, ListNode[] ptr) { if (top \u0026gt; bottom || left \u0026gt; right) return; if (top == bottom) { for (int j=left; j\u0026lt;=right; j++) result[top][j] = getValue(ptr); return; } if (left == right) { for (int i=top; i\u0026lt;=bottom; i++) result[i][left] = getValue(ptr); return; } else { for (int j=left; j\u0026lt;right; j++) result[top][j] = getValue(ptr); for (int i=top; i\u0026lt;bottom; i++) result[i][right] = getValue(ptr); for (int j=right; j\u0026gt;left; j--) result[bottom][j] = getValue(ptr); for (int i=bottom; i\u0026gt;top; i--) result[i][left] = getValue(ptr); } helper(result, top+1, bottom-1, left+1, right-1, ptr); } public int[][] spiralMatrix(int m, int n, ListNode head) { int[][] result = new int[m][n]; ListNode[] ptr = new ListNode[1]; ptr[0] = head; helper(result, 0, m-1, 0, n-1, ptr); return result; } } "},{"id":78,"href":"/docs/codes/2400-to-2499/2487.-Remove-Nodes-From-Linked-List/","title":"2487. Remove Nodes From Linked List","section":"2400 to 2499","content":" 2487. Remove Nodes From Linked List # 题目 # 给定链表头节点head,对于链表中的每个节点node,如果其右侧存在一个具有严格更大值的节点,则移除node。\n返回修改后链表的头节点head。\n思路 # 代码 # 反转\u0026amp;移除 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution{ public ListNode reverseList(ListNode head) { if (head == null || head.next == null) return head; ListNode newHead = reverseList(head.next); head.next.next = head; head.next = null; return newHead; } public ListNode removeNodes(ListNode head) { if (head == null || head.next == null) return head; ListNode sentinel = new ListNode(-1, head); ListNode tail = reverseList(sentinel), ptr = tail; int maxVal = ptr.val; while (ptr.next != sentinel) { if (ptr.next.val \u0026lt; maxVal) ptr.next = ptr.next.next; else { maxVal = ptr.next.val; ptr = ptr.next; } } reverseList(tail); return sentinel.next; } } 递归 # public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class Solution { public ListNode removeNodes(ListNode head) { if (head == null || head.next == null) return head; ListNode ptr = removeNodes(head.next); if (head.val \u0026lt; ptr.val) return ptr; else { head.next = ptr; return head; } } } "},{"id":79,"href":"/docs/codes/reference/buttons/","title":"Buttons","section":"Codes","content":" Buttons # Buttons are styled links that can lead to local page or external link.\nExample # {{\u0026lt; button relref=\u0026#34;/\u0026#34; [class=\u0026#34;...\u0026#34;] \u0026gt;}}Get Home{{\u0026lt; /button \u0026gt;}} {{\u0026lt; button href=\u0026#34;https://github.com/alex-shpak/hugo-book\u0026#34; \u0026gt;}}Contribute{{\u0026lt; /button \u0026gt;}} Get Home Contribute TODO\n将题目的URL替换为leetcode.com的相应链接 标记题目的difficulty 完善每道题目的analysis 融合Anki "},{"id":80,"href":"/docs/codes/reference/columns/","title":"Columns","section":"Codes","content":" Columns # Columns help organize shorter pieces of content horizontally for readability.\n{{\u0026lt; columns \u0026gt;}} \u0026lt;!-- begin columns block --\u0026gt; # Left Content Lorem markdownum insigne... \u0026lt;---\u0026gt; \u0026lt;!-- magic separator, between columns --\u0026gt; # Mid Content Lorem markdownum insigne... \u0026lt;---\u0026gt; \u0026lt;!-- magic separator, between columns --\u0026gt; # Right Content Lorem markdownum insigne... {{\u0026lt; /columns \u0026gt;}} Example # Left Content # Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa protulit, sed sed aere valvis inhaesuro Pallas animam: qui quid, ignes. Miseratus fonte Ditis conubia. Mid Content # Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat stringit, frustra Saturnius uteroque inter! Right Content # Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa protulit, sed sed aere valvis inhaesuro Pallas animam: qui quid, ignes. Miseratus fonte Ditis conubia. "},{"id":81,"href":"/docs/codes/reference/details/","title":"Details","section":"Codes","content":" Details # Details shortcode is a helper for details html5 element. It is going to replace expand shortcode.\nExample # {{\u0026lt; details \u0026#34;Title\u0026#34; [open] \u0026gt;}} ## Markdown content Lorem markdownum insigne... {{\u0026lt; /details \u0026gt;}} {{\u0026lt; details title=\u0026#34;Title\u0026#34; open=true \u0026gt;}} ## Markdown content Lorem markdownum insigne... {{\u0026lt; /details \u0026gt;}} Title Markdown content # Lorem markdownum insigne\u0026hellip; "},{"id":82,"href":"/docs/codes/reference/expand/","title":"Expand","section":"Codes","content":" Expand # Expand shortcode can help to decrease clutter on screen by hiding part of text. Expand content by clicking on it.\nExample # Default # {{\u0026lt; expand \u0026gt;}} ## Markdown content Lorem markdownum insigne... {{\u0026lt; /expand \u0026gt;}} Expand ↕ Markdown content # Lorem markdownum insigne\u0026hellip; With Custom Label # {{\u0026lt; expand \u0026#34;Custom Label\u0026#34; \u0026#34;...\u0026#34; \u0026gt;}} ## Markdown content Lorem markdownum insigne... {{\u0026lt; /expand \u0026gt;}} Custom Label ... Markdown content # Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa protulit, sed sed aere valvis inhaesuro Pallas animam: qui quid, ignes. Miseratus fonte Ditis conubia. "},{"id":83,"href":"/docs/codes/reference/hints/","title":"Hints","section":"Codes","content":" Hints # Hint shortcode can be used as hint/alerts/notification block.\nThere are 3 colors to choose: info, warning and danger.\n{{\u0026lt; hint [info|warning|danger] \u0026gt;}} **Markdown content** Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa {{\u0026lt; /hint \u0026gt;}} Example # Markdown content\nLorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa Markdown content\nLorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa Markdown content\nLorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa "},{"id":84,"href":"/docs/codes/reference/katex/","title":"Katex","section":"Codes","content":" KaTeX # KaTeX shortcode let you render math typesetting in markdown document. See KaTeX\nExample # {{\u0026lt; katex [display] [class=\u0026#34;text-center\u0026#34;] \u0026gt;}} f(x) = \\int_{-\\infty}^\\infty\\hat f(\\xi)\\,e^{2 \\pi i \\xi x}\\,d\\xi {{\u0026lt; /katex \u0026gt;}} \\[f(x) = \\int_{-\\infty}^\\infty\\hat f(\\xi)\\,e^{2 \\pi i \\xi x}\\,d\\xi\\] Display Mode Example # Here is some inline example: \\(\\pi(x)\\) , rendered in the same line. And below is display example, having display: block \\[f(x) = \\int_{-\\infty}^\\infty\\hat f(\\xi)\\,e^{2 \\pi i \\xi x}\\,d\\xi\\] Text continues here.\n"},{"id":85,"href":"/docs/codes/reference/mermaid/","title":"Mermaid","section":"Codes","content":" Mermaid Chart # MermaidJS is library for generating svg charts and diagrams from text.\nOverride Mermaid Initialization Config\nTo override the initialization config for Mermaid, create a mermaid.json file in your assets folder!\nExample # {{\u0026lt; mermaid [class=\u0026#34;text-center\u0026#34;]\u0026gt;}} stateDiagram-v2 State1: The state with a note note right of State1 Important information! You can write notes. end note State1 --\u0026gt; State2 note left of State2 : This is the note to the left. {{\u0026lt; /mermaid \u0026gt;}} stateDiagram-v2 State1: The state with a note note right of State1 Important information! You can write notes. end note State1 --\u003e State2 note left of State2 : This is the note to the left. "},{"id":86,"href":"/docs/codes/reference/tabs/","title":"Tabs","section":"Codes","content":" Tabs # Tabs let you organize content by context, for example installation instructions for each supported platform.\n{{\u0026lt; tabs \u0026#34;uniqueid\u0026#34; \u0026gt;}} {{\u0026lt; tab \u0026#34;MacOS\u0026#34; \u0026gt;}} # MacOS Content {{\u0026lt; /tab \u0026gt;}} {{\u0026lt; tab \u0026#34;Linux\u0026#34; \u0026gt;}} # Linux Content {{\u0026lt; /tab \u0026gt;}} {{\u0026lt; tab \u0026#34;Windows\u0026#34; \u0026gt;}} # Windows Content {{\u0026lt; /tab \u0026gt;}} {{\u0026lt; /tabs \u0026gt;}} Example # MacOS MacOS # This is tab MacOS content.\nLorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa protulit, sed sed aere valvis inhaesuro Pallas animam: qui quid, ignes. Miseratus fonte Ditis conubia.\nLinux Linux # This is tab Linux content.\nLorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa protulit, sed sed aere valvis inhaesuro Pallas animam: qui quid, ignes. Miseratus fonte Ditis conubia.\nWindows Windows # This is tab Windows content.\nLorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa protulit, sed sed aere valvis inhaesuro Pallas animam: qui quid, ignes. Miseratus fonte Ditis conubia.\n"},{"id":87,"href":"/docs/codes/%E5%89%91%E6%8C%87-Offer/06.-%E4%BB%8E%E5%B0%BE%E5%88%B0%E5%A4%B4%E6%89%93%E5%8D%B0%E9%93%BE%E8%A1%A8/","title":"06. 从尾到头打印链表","section":"剑指 Offer","content":" 剑指 Offer 06. 从尾到头打印链表 # 题目 # 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode(int x) { val = x; } } class Solution { public void helper(ListNode head, List\u0026lt;Integer\u0026gt; resultList) { if (head == null) return; else if (head.next == null) resultList.add(head.val); else { helper(head.next, resultList); resultList.add(head.val); } } public int[] reversePrint(ListNode head) { List\u0026lt;Integer\u0026gt; resultList = new ArrayList\u0026lt;\u0026gt;(); helper(head, resultList); int[] result = new int[resultList.size()]; for (int i=0; i\u0026lt;resultList.size(); i++) result[i] = resultList.get(i); return result; } } "},{"id":88,"href":"/docs/codes/%E5%89%91%E6%8C%87-Offer/18.-%E5%88%A0%E9%99%A4%E9%93%BE%E8%A1%A8%E7%9A%84%E8%8A%82%E7%82%B9/","title":"18. 删除链表的节点","section":"剑指 Offer","content":" 剑指 Offer 18. 删除链表的节点 # 题目 # 给定单链表的头指针和一个要删除的节点的值,定义一个函数删除该节点,返回删除后的链表的头节点。链表中节点的值互不相同。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode(int x) { val = x; } } class Solution { public ListNode deleteNode(ListNode head, int val) { if (head.val == val) return head.next; ListNode ptr = head; while (ptr.next.val != val) ptr = ptr.next; ptr.next = ptr.next.next; return head; } } "},{"id":89,"href":"/docs/codes/%E9%9D%A2%E8%AF%95%E9%A2%98/%E9%9D%A2%E8%AF%95%E9%A2%98-02.01.-%E7%A7%BB%E9%99%A4%E9%87%8D%E5%A4%8D%E8%8A%82%E7%82%B9/","title":"面试题 02.01. 移除重复节点","section":"面试题","content":" 面试题 02.01. 移除重复节点 # 题目 # 编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。\n思路 # 代码 # public class ListNode { int val; ListNode next; ListNode(int x) { val = x; } } class Solution { public ListNode removeDuplicateNodes(ListNode head) { if (head == null) return null; HashSet\u0026lt;Integer\u0026gt; record = new HashSet\u0026lt;\u0026gt;(); ListNode ptr = head; while (ptr.next != null) { record.add(ptr.val); if (record.contains(ptr.next.val)) ptr.next = ptr.next.next; else ptr = ptr.next; } return head; } } "},{"id":90,"href":"/docs/codes/%E9%9D%A2%E8%AF%95%E9%A2%98/%E9%9D%A2%E8%AF%95%E9%A2%98-03.03.-%E5%A0%86%E7%9B%98%E5%AD%90/","title":"面试题 03.03. 堆盘子","section":"面试题","content":" 面试题 03.03. 堆盘子 # 题目 # 堆盘子。设想有一堆盘子,堆太高可能会倒下来。因此,在现实生活中,盘子堆到一定高度时,就会堆另外一堆盘子。实现数据结构 SetOfStacks,模拟这种行为。SetOfStacks 应该由多个栈组成,并在在前一个栈填满时新建一个栈。此外,SetOfStacks.push()和 SetOfStacks.pop() 应该与普通栈的操作方法相同 (即,pop 的返回值应该与只有一个栈时的情况一致)。此外,实现 popAt(int index) 方法,根据指定的子栈,执行 pop 操作。\n当某个栈为空时,应删除该栈。当栈中没有元素或不存在该栈时,pop,popAt 应返回 -1。\n思路 # 代码 # class StackOfPlates { private class stackNode { public int val; public stackNode next; stackNode(int val, stackNode next) { this.val = val; this.next = next; } } private class Stack { private int size; private int capacity; private stackNode sentinel; Stack(int capacity) { this.size = 0; this.capacity = capacity; this.sentinel = new StackNode(-1, null); } public void push (int val) { this.sentinel.next = new stackNode(val, this.sentinel.next); this.size += 1; } public int pop() { int result = this.sentinel.next.val; this.sentinel.next = this.sentinel.next.next; this.size -= 1; return result; } public boolean isEmpty() { return this.size == 0; } public boolean isFull() { return this.size == this.capacity; } } private class ListNode { Stack stack; ListNode prev; ListNode next; ListNode(int capacity, ListNode prev, ListNode next) { this.stack = new Stack(capacity); this.prev = prev; this.next = next; } } private ListNode sentinel; private int capacity; public StackOfPlates(int cap) { this.sentinel = new ListNode(cap, null, null); this.sentinel.prev = this.sentinel.next = this.sentinel; this.capacity = cap; } public void push(int val) { if (this.capacity == 0) return; if (this.isEmpty() == true || this.sentinel.prev.stack.isFull() == true) { this.sentinel.prev = new ListNode(this.capacity, this.sentinel.prev, this.sentinel); this.sentinel.prev.prev.next = this.sentinel.prev; } this.sentinel.prev.stack.push(val); } public int pop() { if (this.isEmpty() == true) return -1; int result = this.sentinel.prev.stack.pop(); if (this.sentinel.prev.stack.isEmpty() == true) delete(this.sentinel.prev); return result; } public int popAt(int index) { if (this.isEmpty() == true) return -1; ListNode ptr = this.sentinel.next; for(int i=0; i\u0026lt;index; i++) { ptr = ptr.next; if (ptr == this.sentinel) return -1; } int result = ptr.stack.pop(); if (ptr.stack.isEmpty() == true) delete(ptr); return result; } public boolean isEmpty() { return this.sentinel.prev == this.sentinel; } public void delete(ListNode ptr) { ptr.prev.next = ptr.next; ptr.next.prev = ptr.prev; } } "},{"id":91,"href":"/docs/topic/hidden/","title":"Hidden","section":"Topic","content":" This page is hidden in menu # Quondam non pater est dignior ille Eurotas # Latent te facies # Lorem markdownum arma ignoscas vocavit quoque ille texit mandata mentis ultimus, frementes, qui in vel. Hippotades Peleus pennas conscia cuiquam Caeneus quas.\nPater demittere evincitque reddunt Maxime adhuc pressit huc Danaas quid freta Soror ego Luctus linguam saxa ultroque prior Tatiumque inquit Saepe liquitur subita superata dederat Anius sudor Cum honorum Latona # O fallor in sustinui iussorum equidem. Nymphae operi oris alii fronde parens dumque, in auro ait mox ingenti proxima iamdudum maius?\nreality(burnDocking(apache_nanometer), pad.property_data_programming.sectorBrowserPpga(dataMask, 37, recycleRup)); intellectualVaporwareUser += -5 * 4; traceroute_key_upnp /= lag_optical(android.smb(thyristorTftp)); surge_host_golden = mca_compact_device(dual_dpi_opengl, 33, commerce_add_ppc); if (lun_ipv) { verticalExtranet(1, thumbnail_ttl, 3); bar_graphics_jpeg(chipset - sector_xmp_beta); } Fronde cetera dextrae sequens pennis voce muneris # Acta cretus diem restet utque; move integer, oscula non inspirat, noctisque scelus! Nantemque in suas vobis quamvis, et labori!\nvar runtimeDiskCompiler = home - array_ad_software; if (internic \u0026gt; disk) { emoticonLockCron += 37 + bps - 4; wan_ansi_honeypot.cardGigaflops = artificialStorageCgi; simplex -= downloadAccess; } var volumeHardeningAndroid = pixel + tftp + onProcessorUnmount; sector(memory(firewire + interlaced, wired)); "}]