-
Notifications
You must be signed in to change notification settings - Fork 0
/
en.search-data.min.70deba39b270b2ba721ef7509fe49f857268b380af4870244d4edc86e93de23c.json
1 lines (1 loc) · 453 KB
/
en.search-data.min.70deba39b270b2ba721ef7509fe49f857268b380af4870244d4edc86e93de23c.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 😎 0109. Convert Sorted List to Binary Search Tree Medium 0114. Flatten Binary Tree to Linked List Medium 0116. Populating Next Right Pointers in Each Node Java Medium 0117. Populating Next Right Pointers in Each Node 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 Java 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 0426. Convert Binary Search Tree to Doubly Linked List 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 0705. Design HashSet Easy 😎😎😎 0706. Design HashMap Easy 😎😎😎 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 1206. Design Skiplist Java Hard 😎😎😎 1265. Print Immutable Linked List in Reverse Java Medium 1290. Convert Binary Number in a Linked List to Integer Java Easy 1367. Linked List in Binary Tree Medium 1472. Design Browser History Java Medium 1474. Delete N Nodes after M Nodes of a Linked List Java Easy 1634. Add Two Polynomials Represented as Linked Lists Java Medium 1669. Merge In Between Linked Lists Java Medium 1670. Design Front Middle Back Queue Java Medium 1721. Swapping Nodes in a Linked List Java Medium 1836. Remove Duplicates From an Unsorted Linked List Java Medium 2046. Sort Linked List Already Sorted Using Absolute Values Java Medium 2058. Find the Minimum and Maximum Number of Nodes Between Critical Points Java Medium 2074. Reverse Nodes in Even Length Groups Java Medium 2095. Delete the Middle Node of a Linked List Java Medium 2130. Maximum Twin Sum of a Linked List Java Medium 2181. Merge Nodes in Between Zeros Java Medium 2289. Steps to Make Array Non-decreasing Java Medium 😎😎😎 2296. Design a Text Editor Java Hard 😎😎 2326. Spiral Matrix IV Java Medium 2487. Remove Nodes From Linked List Java Medium Interview 03.03. Stack of Plates LCCI 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":"/docs/templates/SkipList/","title":"3.03 SkipList","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":10,"href":"/docs/templates/HashMap/","title":"3.04 HashMap","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":11,"href":"/docs/templates/bit/","title":"3.05 Bit Operation","section":"Templates","content":" 位运算 # 位运算符 # Symbol Description Rule \u0026amp; 与 1 \u0026amp; 1 = 1, 0 ^ x = 0 ` ` 或 ~ 非 ~1 = 0, ~0 = 1 ^ 异或 0 ^ 1 = 1, 1 ^ 1 = 0, 0 ^ 0 = 0 \u0026lt;\u0026lt; 左移 各二进制位全部左移若干位,高位丢弃,低位补零 \u0026gt;\u0026gt; 算术右移 各二进制位全部右移若干位,高位补符号位 \u0026gt;\u0026gt;\u0026gt; 逻辑右移 各二进制位全部右移若干位,高位补零 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":12,"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":13,"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":14,"href":"/docs/codes/0001-to-0099/0001.-Two-Sum/","title":"0001. Two Sum","section":"0001 to 0099","content":" 0001. Two Sum # 题目 # 给定一个整数数组 nums 和一个整数目标值 target。\n在该数组中找出 和为目标值 target 的 两个 整数,并返回它们的数组下标。\n假定每种输入只会对应一个答案。\n数组中同一个元素在答案里不能重复出现。\n思路 # 哈希 # 遍历数组,对于元素 x,若 target-x 已被访问,则找到 和为目标值 target 的两个整数。 在遍历数组时使用 HashMap 建立 数组元素 至 数组下标 的映射。 HashMap 可实现对于 元素是否被访问过 的判断。 代码 # 哈希 # class Solution { public int[] twoSum(int[] nums, int target) { int[] ans = new int[2]; 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) { ans[0] = map.get(target - nums[i]); ans[1] = i; } else { map.put(nums[i], i); } } return ans; } } "},{"id":15,"href":"/docs/codes/0001-to-0099/0002.-Add-Two-Numbers/","title":"0002. Add Two Numbers","section":"0001 to 0099","content":" 0002. Add Two Numbers # 题目 # 给定两个 非空 链表,表示两个非负整数。 每位数字均按 逆序 方式存储,每个节点只存储一位数字。 将两个数相加,并以相同形式返回一个表示和的链表。 假定除数字 0 之外,这两个数均不会以 0 开头。 解释 342 + 465 = 807\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 recursive(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, recursive(l1.next, null, (l1.val + carry) / 10)); } else if (l1 == null \u0026amp;\u0026amp; l2 != null) { return new ListNode((l2.val + carry) % 10, recursive(null, l2.next, (l2.val + carry) / 10)); } else { ListNode node = new ListNode((l1.val + l2.val + carry) % 10, null); node.next = recursive(l1.next, l2.next, (l1.val + l2.val + carry) / 10); return node; } } public ListNode addTwoNumbers(ListNode l1, ListNode l2) { return recursive(l1, l2, 0); } } "},{"id":16,"href":"/docs/codes/0001-to-0099/0013.-Roman-to-Integer/","title":"0013. Roman to Integer","section":"0001 to 0099","content":" 0013. Roman to Integer # 题目 # 罗马数字包含七种字符: I, V,X, L,C,D 和 M。\n字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 写做 II,12 写做 XII,27 写做 XXVII。\n罗马数字中小数字通常位于大数字的右侧,但存在以下六种特例\nI 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。 X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。 给定一个罗马数字,将其转换为整数。\n思路 # 模拟 # 代码 # 模拟 # class Solution { public int romanToInt(String s) { int ans = 0; for (int i = 0; i \u0026lt; s.length(); i++) { if (s.charAt(i) == \u0026#39;V\u0026#39;) ans += 5; else if (s.charAt(i) == \u0026#39;L\u0026#39;) ans += 50; else if (s.charAt(i) == \u0026#39;D\u0026#39;) ans += 500; else if (s.charAt(i) == \u0026#39;M\u0026#39;) ans += 1000; else if (s.charAt(i) == \u0026#39;I\u0026#39;) { if (i + 1 \u0026lt; s.length() \u0026amp;\u0026amp; s.charAt(i + 1) == \u0026#39;V\u0026#39;) { ans += 4; i += 1; } else if (i + 1 \u0026lt; s.length() \u0026amp;\u0026amp; s.charAt(i + 1) == \u0026#39;X\u0026#39;) { ans += 9; i += 1; } else ans += 1; } else if (s.charAt(i) == \u0026#39;X\u0026#39;) { if (i + 1 \u0026lt; s.length() \u0026amp;\u0026amp; s.charAt(i + 1) == \u0026#39;L\u0026#39;) { ans += 40; i += 1; } else if (i + 1 \u0026lt; s.length() \u0026amp;\u0026amp; s.charAt(i + 1) == \u0026#39;C\u0026#39;) { ans += 90; i += 1; } else ans += 10; } else if (s.charAt(i) == \u0026#39;C\u0026#39;) { if (i + 1 \u0026lt; s.length() \u0026amp;\u0026amp; s.charAt(i + 1) == \u0026#39;D\u0026#39;) { ans += 400; i += 1; } else if (i + 1 \u0026lt; s.length() \u0026amp;\u0026amp; s.charAt(i + 1) == \u0026#39;M\u0026#39;) { ans += 900; i += 1; } else ans += 100; } } return ans; } } "},{"id":17,"href":"/docs/codes/0001-to-0099/0014.-Longest-Common-Prefix/","title":"0014. Longest Common Prefix","section":"0001 to 0099","content":" 0014. Longest Common Prefix # 题目 # 编写一个函数来查找字符串数组中的最长公共前缀。 若不存在公共前缀,返回空字符串 \u0026quot;\u0026quot;。 思路 # 模拟 # 代码 # 模拟 # class Solution { public String longestCommonPrefix(String[] strs) { String ans = \u0026#34;\u0026#34;; int candidate = 0; while (true) { for (String str: strs) { if (candidate == str.length() || str.charAt(candidate) != strs[0].charAt(candidate)) return ans; } ans += Character.toString(strs[0].charAt(candidate++)); } return ans; } } "},{"id":18,"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":" 0019. Remove Nth Node from End of List # 题目 # 删除给定链表的倒数第 n 个节点,并且返回头节点。 尝试使用一趟扫描实现。 思路 # 双指针 # 若要删除单链表的倒数第 n 个节点,需定位单链表的倒数第 n + 1 个节点。 考虑快慢指针,令快指针先走 n + 1步,之后双指针同步前进至快指针为空。 此时慢指针指向单链表的倒数第 n + 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 removeNthFromEnd(ListNode head, int n) { ListNode sentinel = new ListNode(-1, head), slow = sentinel, fast = sentinel; 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":19,"href":"/docs/codes/0001-to-0099/0020.-Valid-Parentheses/","title":"0020. Valid Parentheses","section":"0001 to 0099","content":" 0020. Valid Parenthesis # 题目 # 给定一个只包括 '(', ')','{','}','[',']' 的字符串 s,判断字符串是否有效。\n有效字符串需满足:\n左括号必须用相同类型的右括号闭合。\n左括号必须以正确的顺序闭合。\n每个右括号都有一个对应的相同类型的左括号。\n思路 # 栈 # 可使用 栈 求解括号匹配问题 逢左括号入栈,逢右括号出栈 逢右括号 不匹配 / 遇栈空,或遍历结束时栈非空,则括号失配 代码 # 栈 # class Solution { public boolean isValid(String s) { Stack\u0026lt;Character\u0026gt; stack = new Stack\u0026lt;\u0026gt;(); for (int i=0; i\u0026lt;s.length(); i++) { /** 逢左括号入栈 */ char bracket = s.charAt(i); if (bracket == \u0026#39;{\u0026#39; || bracket == \u0026#39;(\u0026#39; || bracket == \u0026#39;[\u0026#39;) { stack.push(bracket); continue; } /** 逢右括号出栈并检查匹配情况 */ if (stack.empty() == true) reutrn false; char topElement = stack.pop(); if (bracket == \u0026#39;)\u0026#39; \u0026amp;\u0026amp; topElement != \u0026#39;(\u0026#39;) return false; if (bracket == \u0026#39;}\u0026#39; \u0026amp;\u0026amp; topElement != \u0026#39;{\u0026#39;) return false; if (bracket == \u0026#39;]\u0026#39; \u0026amp;\u0026amp; topElement != \u0026#39;[\u0026#39;) return false; } return stack.empty() == true; } } "},{"id":20,"href":"/docs/codes/0001-to-0099/0021.-Merge-Two-Sorted-Lists/","title":"0021. Merge Two Sorted Lists","section":"0001 to 0099","content":" 0021. Merge Two Sorted Lists # 题目 # 将两个升序链表合并为一个新的升序链表并返回。 新链表是通过拼接给定的两个链表的所有节点组成的。 思路 # 递归 # 代码 # 递归 # 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":21,"href":"/docs/codes/0001-to-0099/0023.-Merge-K-Sorted-Lists/","title":"0023. Merge K Sorted Lists","section":"0001 to 0099","content":" 23. Merge k Sorted Lists # 题目 # 给定一个链表数组,每个链表都已经按升序排列。\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) {xcys_HY5 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":22,"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":23,"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":24,"href":"/docs/codes/0001-to-0099/0026.-Remove-Duplicates-from-Sorted-Array/","title":"0026. Remove Duplicates From Sorted Array","section":"0001 to 0099","content":" 26. Remove Duplicates from Sorted Array # 题目 # 给定一个 升序排列 的数组 nums,原地删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致。\n如果在删除重复项后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。\n将最终结果插入 nums 的前 k 个位置后返回 k。\n在 原地 修改输入数组并在使用 O(1) 额外空间的条件下完成。\n思路 # 双指针 代码 # class Solution { public int removeDuplicates(int[] nums) { if (nums.length == 1) return 1; /** 双指针法 */ int i = 0, j = 1; while (j \u0026lt; nums.length) { if (nums[j] != nums[i]) nums[++i] = nums[j]; j += 1; } return i + 1; } } "},{"id":25,"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":26,"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":27,"href":"/docs/codes/0001-to-0099/0058.-Length-of-Last-Word/","title":"0058. Length of Last Word","section":"0001 to 0099","content":" 0059. Length of Last Word # 题目 # 给定字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是仅由字母组成,不包含任何空格字符的最大子字符串。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int lengthOfLastWord(String s) { int start = -1, end = s.length() - 1; while (end \u0026gt; -1 \u0026amp;\u0026amp; s.charAt(end) == \u0026#39; \u0026#39;) end -= 1; if (end == -1) return 0; start = end; while (start \u0026gt; 0 \u0026amp;\u0026amp; s.charAt(start) != \u0026#39; \u0026#39;) start -= 1; return end - start; } } "},{"id":28,"href":"/docs/codes/0001-to-0099/0059.-Spiral-Matrix-ii/","title":"0059. Spiral Matrix Ii","section":"0001 to 0099","content":" 0059. 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":29,"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":30,"href":"/docs/codes/0001-to-0099/0066.-Plus-One/","title":"0066. Plus One","section":"0001 to 0099","content":" 0066. Plus One # 题目 # 给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。\n最高位数字存放在数组的首位,数组中每个数字只存储 单个 数字。\n可以假定除整数 0 之外,这个整数不会以零开头。\n思路 # 代码 # class Solution { public int[] plusOne(int[] digits) { int carry = 1; for (int i = digits.length - 1; i \u0026gt;= 0; i--) { int newDigit = (digits[i] + carry) % 0; carry = (digits[i] + carry) / 10; digits[i] = newDigit; } if (carry == 0) return digits; int[] ans = new int[digits.length + 1]; ans[0] = carry; for (int i = 0; i \u0026lt; digits.length; i++) ans[i + 1] = digits[i]; return ans; } } "},{"id":31,"href":"/docs/codes/0001-to-0099/0067.-Add-Binary/","title":"0067. Add Binary","section":"0001 to 0099","content":" 0067. Add Binary # 题目 # 给定两个二进制字符串a和b,以二进制字符串的形式返回它们的和。 思路 # 模拟 # 代码 # 模拟 # class Solution { public String addBinary(String a, String b) { String longer = a.length() \u0026gt; b.length() ? a : b; int ptrLonger = longer.length() - 1; String shorter = a.length() \u0026gt; b.length() ? b : a; int ptrShorter = shorter.length() - 1; char[] ans = longer.toCharArray(); int sum = 0, carry = 0; while (ptrShorter \u0026gt;= 0) { sum = longer.charAt(ptrLonger) - \u0026#39;0\u0026#39; + shorter.charAt(ptrShorter) - \u0026#39;0\u0026#39; + carry; ans[ptrLonger] = sum % 2 ? 0 ? \u0026#39;1\u0026#39; : \u0026#39;0\u0026#39;; carry = sum \u0026gt; 1 ? 1 : 0; ptrLonger--; ptrShorter--; } while (carry \u0026gt; 0) { if (ptrLonger == -1) return \u0026#34;1\u0026#34; + String.valueOf(ans); sum = ans[ptrLonger] - \u0026#39;0\u0026#39; + carry; ans[ptrLonger--] = sum % 2 \u0026gt; 0 ? \u0026#39;1\u0026#39; : \u0026#39;0\u0026#39;; carry = sum \u0026gt; 1 ? 1 : 0; } return String.valueOf(ans); } } 致谢 # 负雪明烛\n"},{"id":32,"href":"/docs/codes/0001-to-0099/0070.-Climbing-Stairs/","title":"0070. Climbing Stairs","section":"0001 to 0099","content":" 70. Climbing Stairs # 题目 # 假定某人正在爬楼梯,需要 n 阶才能到达楼顶。\n每次可以爬 1 或 2 个台阶。求出爬到楼顶的方案总数。\n思路 # 代码 # class Solution { public int climbStairs(int n) { if (n == 1 || n == 2) return n; int prev = 1, cur = 2; for (int i = 3; i \u0026lt;= n; i++) { int temp = prev + cur; prev = cur; cur = temp; } return cur; } } "},{"id":33,"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":34,"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":35,"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":36,"href":"/docs/codes/0001-to-0099/0088.-Merge-Sorted-Array/","title":"0088. Merge Sorted Array","section":"0001 to 0099","content":" 0088. Merge Sorted Array # 题目 # 给定两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。 合并后的元素存储在数组 nums1 中。设置 nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。 思路 # 双指针 # 数组 nums1 和 nums2 是有序数组。 从前向后遍历时需要移动数组元素,从后向前遍历会简化过程。 代码 # 双指针 # class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { int ptr1 = m - 1, ptr2 = n - 1, ptr = m + n - 1; while (ptr1 \u0026gt; -1 \u0026amp;\u0026amp; ptr2 \u0026gt; -1) nums1[ptr--] = nums1[ptr1] \u0026gt;= nums2[ptr2] ? nums1[ptr1--] : nums2[ptr2--]; while (ptr \u0026gt; -1) nums1[ptr--] = ptr1 \u0026gt; -1 ? nums1[ptr1--] : nums2[ptr2--]; } } 致谢 # Ikaruga\n"},{"id":37,"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":38,"href":"/docs/codes/0001-to-0099/0094.-Binary-Tree-Inorder-Traversal/","title":"0094. Binary Tree Inorder Traversal","section":"0001 to 0099","content":" 94. Binary Tree Inorder Traversal # 题目 # 给定二叉树的根节点 root,返回它节点值的 中序 遍历。\n思路 # 代码 # 暴力解 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public void traversal(TreeNode root, List\u0026lt;Integer\u0026gt; ans) { if (root == null) return; traverse(root.left, ans); ans.add(root.val); traverse(root.right, ans); } public List\u0026lt;Integer\u0026gt; inorderTraversal(TreeNode root) { List\u0026lt;Integer\u0026gt; ans = new ArrayList\u0026lt;\u0026gt;(); traverse(root, ans); return ans; } } "},{"id":39,"href":"/docs/codes/0001-to-0099/0098.-Validate-Binary-Search-Tree/","title":"0098. Validate Binary Search Tree","section":"0001 to 0099","content":" 0098. Validate Binary Search Tree # 题目 # 给定二叉树根节点 root,判断其是否是一个有效的 BST 有效 BST 定义如下 节点的左子树只包含 小于 当前节点的数 节点的右子树只包含 大于 当前节点的数 所有左子树和右子树自身也须是 BST 思路 # 中序遍历 # 代码 # 中序遍历+列表 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public void reverse(TreeNode root, List\u0026lt;Integer\u0026gt; values) { if (root == null) return; traverse(root.left, values); values.add(root.val); traverse(root.right, values); } public boolean isValidBST(TreeNode root) { List\u0026lt;Integer\u0026gt; values = new LinkedList\u0026lt;\u0026gt;(); traverse(root, values); for (int i = 0; i \u0026lt; values.size() - 1; i++) { if (values.get(i) \u0026gt;= values.get(i + 1)) return false; } return true; } } 中序遍历+全局变量 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { private long pre = Long.MIN_VALUE; public boolean traverse(TreeNode root) { if (root == null) return true; boolean ans = traverse(root.left) \u0026amp;\u0026amp; this.pre \u0026lt; root.val; if (ans == false) return false; this.pre = root.val; return traverse(root.right); } public boolean isValidBST(TreeNode root) { return traverse(root); } } 致谢https://leetcode.cn/problems/validate-binary-search-tree/solutions/2082978/yan-zheng-er-cha-sou-suo-shu-di-gui-fa-b-zt9r/ # PlanB\n"},{"id":40,"href":"/docs/codes/0100-to-0199/0100.-Same-Tree/","title":"0100. Same Tree","section":"0100 to 0199","content":" 100. Same Tree # 题目 # 给定两棵二叉树的根节点 p 和 q,判断这两棵树是否相同。\n若两棵树在结构上相同,并且节点具有相同的值,则认为它们是相同的。\n思路 # 代码 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public boolean isSameTree(TreeNode p, TreeNode q) { if (p == null) return q == null; if (q == null) return false; return (p.val == q.val) \u0026amp; isSameTree(p.left, q.left) \u0026amp; isSameTree(p.right, q.right); } } "},{"id":41,"href":"/docs/codes/0100-to-0199/0101.-Symmetric-Tree/","title":"0101. Symmetric Tree","section":"0100 to 0199","content":" 101. Symmetric Tree # 题目 # 给定二叉树的根节点 root,检查它是否轴对称。\n思路 # 代码 # 递归 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public boolean checkTwoNodes(TreeNode node1, TreeNode2) { if (node1 == null \u0026amp;\u0026amp; node2 == null) return true; if (node1 == null \u0026amp;\u0026amp; node2 != null) return false; if (node1 != null \u0026amp;\u0026amp; node2 == null) return false; if (node1.val != node2.val) return false; return checkTwoNodes(node1.left, node2.right) \u0026amp; checkTwoNodes(node1.right, node2.left); } public boolean isSymmetric(TreeNode root) { return checkTwoNodes(root.left, root.right); } } "},{"id":42,"href":"/docs/codes/0100-to-0199/0102.-Binary-Tree-Level-Order-Traversal/","title":"0102. Binary Tree Level Order Traversal","section":"0100 to 0199","content":" 102. Binary Tree Level Order Traversal # 题目 # 给定二叉树的根节点 root,返回其节点值的 层序遍历。\n即逐层地,从左到右访问所有节点。\n思路 # 代码 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public List\u0026lt;List\u0026lt;Integer\u0026gt;\u0026gt; levelOrder(TreeNode root) { List\u0026lt;List\u0026lt;Integer\u0026gt;\u0026gt; ans = new LinkedList\u0026lt;\u0026gt;(); if (root == null) return ans; Queue\u0026lt;TreeNode\u0026gt; queue = new LinkedList\u0026lt;\u0026gt;(); queue.offer(root); while (queue.size() != 0) { ans.add(new LinkedList\u0026lt;\u0026gt;()); for (int i = 0, layerSize = queue.size(); i \u0026lt; layerSize; i++) { TreeNode node = queue.poll(); ans.get(ans.size() - 1).add(node.val); if (node.left != null) queue.offer(node.left); if (node.right != null) queue.offer(node.right); } } return ans; } } "},{"id":43,"href":"/docs/codes/0100-to-0199/0103.-Binary-Tree-Zigzag-Level-Order-Traversal/","title":"0103. Binary Tree Zigzag Level Order Traversal","section":"0100 to 0199","content":" 103. Binary Tree Zigzag Level Order Traversal # 题目 # 给定二叉树的根节点 root,返回其节点值的 锯齿形层序遍历。\n即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行。\n思路 # 双栈 代码 # 双栈 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public List\u0026lt;List\u0026lt;Integer\u0026gt;\u0026gt; zigzagLevelOrder(TreeNode root) { List\u0026lt;List\u0026lt;Integer\u0026gt;\u0026gt; ans = new LinkedList\u0026lt;\u0026gt;(); if (root == null) return ans; Stack\u0026lt;TreeNode\u0026gt; leftStack = new Stack\u0026lt;\u0026gt;(); Stack\u0026lt;TreeNode\u0026gt; rightStack = new Stack\u0026lt;\u0026gt;(); leftStack.push(root); while (leftStack.size() != 0 || rightStack.size() != 0) { ans.add(new LinkedList\u0026lt;\u0026gt;()); if (leftStack.size() != 0) { while (leftStack.size() != 0) { TreeNode node = leftStack.pop(); ans.get(ans.size() - 1).add(node.val); if (node.left != null) rightStack.push(node.left); if (node.right != null) rightStack.push(node.right); } } else { while (rightStack.size() != 0) { TreeNode node = rightStack.pop(); ans.get(ans.size() - 1).add(node.val); if (node.right != null) leftStack.push(node.right); if (node.left != null) leftStack.push(node.left); } } } return ans; } } "},{"id":44,"href":"/docs/codes/0100-to-0199/0104.-Maximum-Depth-of-BInary-Tree/","title":"0104. Maximum Depth of Binary Tree","section":"0100 to 0199","content":" 104. Maximum Depth of Binary Tree # 题目 # 给定一个二叉树,找出其最大深度。\n二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。\n思路 # 代码 # 递归 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public int maxDepth(TreeNode root) { if (root == null) return 0; return 1 + Math.max(maxDepth(root.left), maxDepth(root.right)); } } "},{"id":45,"href":"/docs/codes/0100-to-0199/0107.-Binary-Tree-Level-Order-Traversal-II/","title":"0107. Binary Tree Level Order Traversal Ii","section":"0100 to 0199","content":" 107. Binary Tree Level Order Traversal II # 题目 # 给定二叉树的根节点 root,返回其节点值 自底向上的层序遍历。\n从叶子节点所在层到根节点所在的层,逐层从左向右遍历。\n思路 # 队列的栈: 先建栈,后出栈 代码 # 递归 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public List\u0026lt;List\u0026lt;Integer\u0026gt;\u0026gt; levelOrderBottom(TreeNode root) { List\u0026lt;List\u0026lt;Integer\u0026gt;\u0026gt; ans = new LinkedList\u0026lt;\u0026gt;(); if (root == null) return ans; Stack\u0026lt;Queue\u0026lt;TreeNode\u0026gt;\u0026gt; stack = new Stack\u0026lt;\u0026gt;(); stack.push(new LinkedList\u0026lt;\u0026gt;()); stack.peek().offer(root); boolean traversalNotEnd = true; while (traversalNotEnd == true) { traversalNotEnd = false; Queue\u0026lt;TreeNode\u0026gt; queue = stack.peek(); stack.push(new LinkedList\u0026lt;\u0026gt;()); for (TreeNode node: queue) { if (node.left == null \u0026amp;\u0026amp; node.right == null) continue; if (node.left != null) stack.peek().offer(node.left); if (node.right != null) stack.peek().offer(node.right); traversalNotEnd = true; } if (traversalNotEnd == false) stack.pop(); } while (stack.size() != 0) { Queue\u0026lt;TreeNode\u0026gt; queue = stack.pop(); ans.add(new LinkedList\u0026lt;\u0026gt;()); for (TreeNode node:queue) ans.get(ans.size() - 1).add(node.val); } return ans; } } "},{"id":46,"href":"/docs/codes/0100-to-0199/0110.-Balanced-Binary-Tree/","title":"0110. Balanced Binary Tree","section":"0100 to 0199","content":" 110. Balanced Binary Tree # 题目 # 给定一棵二叉树,判断其是否为高度平衡的二叉树。\n高度平衡二叉树定义为:每个节点的左右两个子树的高度差的绝对值不超过1。\n思路 # 编写代码的过程中会发现,需要类型分别为 boolean 和 int 的两个返回值,对应 以 root 为根节点的树是否高度平衡 和 以 root 为根节点的树的高度 鉴于树高为非负整数,故负整数可用于表示 以 root 为根节点的树非高度平衡 树的高度通过子树的高度计算得出。且负树高具有传递性。 代码 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { /** 以 -1 表示 root 非高度平衡二叉树 */ public int depth(TreeNode root) { if (root == null) return 0; int leftDepth = depth(root.left); if (leftDepth == -1) return -1; int rightDepth = depth(root.right); if (rightDepth == -1) return -1; if (Math.abs(leftDepth - rightDepth) \u0026gt; 1) return -1; return 1 + Math.max(leftDepth, rightDepth); } public boolean isBalanced(TreeNode root) { return depth(root) != -1; } } 致谢 # 灵茶山艾府\n"},{"id":47,"href":"/docs/codes/0100-to-0199/0111.-Minimum-Depth-of-Binary-Tree/","title":"0111. Minimum Depth of Binary Tree","section":"0100 to 0199","content":" 111. Minimum Depth of Binary Tree # 题目 # 给定一个二叉树,找出其最小深度。\n最小深度是从根节点到最近叶子节点的最短路径上的节点数量。\n思路 # 代码 # 递归 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public int minDepth(TreeNode root) { if (root == null) return 0; if (root.left == null) return 1 + minDepth(root.right); if (root.right == null) return 1 + minDepth(root.left); return 1 + Math.min(minDepth(root.left), minDepth(root.right)); } } "},{"id":48,"href":"/docs/codes/0100-to-0199/0112.-Path-Sum/","title":"0112. Path Sum","section":"0100 to 0199","content":" 112. Path Sum # 题目 # 给定二叉树的根节点 root 和一个表示目标和的整数 targetSum。判断该树上是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum。\n叶子节点 是指没有子节点的节点。\n思路 # 代码 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public boolean hasPathSum(TreeNode root, int targetSum) { if (root == null) return false; if (root.val == targetSum \u0026amp;\u0026amp; root.left == null \u0026amp;\u0026amp; root.right == null) return true; return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val); } } "},{"id":49,"href":"/docs/codes/0100-to-0199/0116.-Populating-Next-Right-Pointers-in-Each-Node/","title":"0116. Populating Next Right Pointers in Each Node","section":"0100 to 0199","content":" 0116. Populating Next Right Pointers in Each Node # 题目 # 给定一个 完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。\n填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。\n初始状态下,所有 next 指针都被设置为 NULL。\n思路 # 层序遍历 代码 # 层序遍历 # class Node { public int val; public Node left; public Node right; public Node next; public Node() {} public Node(int _val) { val = _val; } public Node(int _val, Node _left, Node _right, Node _next) { val = _val; left = _left; right = _right; next = _next; } } class Solution { public Node connect(Node root) { if (root == null) return null; Queue\u0026lt;Node\u0026gt; queue = new LinkedList\u0026lt;\u0026gt;(); queue.offer(root); while (queue.size() != 0) { for (int i = 0, layerSize = queue.size(); i \u0026lt; layerSize; i++) { Node node = queue.poll(); if (i != layerSize - 1) node.next = queue.peek(); if (node.left != null) { queue.offer(node.left); queue.offer(node.right); } } } return root; } } "},{"id":50,"href":"/docs/codes/0100-to-0199/0117.-Populating-Next-Right-Pointers-in-Each-Node-ii/","title":"0117. Populating Next Right Pointers in Each Node Ii","section":"0100 to 0199","content":" 0117. Populating Next Right Pointers in Each Node II # 题目 # 给定一个二叉树\nstruct Node { int val; Node *left; Node *right; Node *next; } 填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。\n初始状态下,所有 next 指针都被设置为 NULL。\n思路 # 层序遍历 代码 # 层序遍历 # class Node { public int val; public Node left; public Node right; public Node next; public Node() {} public Node(int _val) { val = _val; } public Node(int _val, Node _left, Node _right, Node _next) { val = _val; left = _left; right = _right; next = _next; } } class Solution { public Node connect(Node root) { if (root == null) return null; Queue\u0026lt;Node\u0026gt; queue = new LinkedList\u0026lt;\u0026gt;(); queue.offer(root); while (queue.size() != 0) { for (int i = 0, layerSize = queue.size(); i \u0026lt; layerSize; i++) { Node node = queue.poll(); if (i != layerSize - 1) node.next = queue.peek(); if (node.left != null) queue.offer(node.left); if (node.right != null) queue.offer(node.right); } } return root; } } "},{"id":51,"href":"/docs/codes/0100-to-0199/0118.-Pascals-Triangle/","title":"0118. Pascal's Triangle","section":"0100 to 0199","content":" 0118. Pascal\u0026rsquo;s Triangle # 题目 # 给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。 「杨辉三角」中,每个数是它左上方和右上方的数之和。 思路 # 模拟 # 代码 # 模拟 # class Solution { public List\u0026lt;List\u0026lt;Integer\u0026gt;\u0026gt; generate(int numRows) { List\u0026lt;List\u0026lt;Integer\u0026gt;\u0026gt; ans = new LinkedList\u0026lt;\u0026gt;(); ans.add(new LinkedList\u0026lt;\u0026gt;()); ans.get(0).add(1); if (numRows == 1) return ans; for (int i = 1; i \u0026lt; numRows; i++) { ans.add(new LinkedList\u0026lt;\u0026gt;()); ans.get(i).add(1); for (int j = 0; j \u0026lt; ans.get(i - 1).size() - 1; j++) { ans.get(i).add(ans.get(i - 1).get(j) + ans.get(i - 1).get(j + 1)); } ans.get(i).add(1); } return ans; } } "},{"id":52,"href":"/docs/codes/0100-to-0199/0121.-Best-Time-to-Buy-ans-Sell-Stock/","title":"0121. Best Time to Buy Ans Sell Stock","section":"0100 to 0199","content":" 0121. Best Time to Buy and Sell Stock # 题目 # 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。\n只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。\n返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。\n思路 # 贪心 # 代码 # 贪心 # class Solution { public int maxProfit(int[] prices) { int ans = 0, minPrice = prices[0]; for (int price: prices) { minPrice = Math.min(minPrice, price); ans = Math.max(ans, price - minPrice); } return ans; } } "},{"id":53,"href":"/docs/codes/0100-to-0199/0125.-Valid-Palindrome/","title":"0125. Valid Palindrome","section":"0100 to 0199","content":" 0125. Valid Palindrome # 题目 # 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样,则可以认为该短语是一个 回文串。\n字母和数字都属于字母数字字符。\n给定字符串 s,判断其是否为 回文串。\n思路 # 代码 # class Solution { public boolean isPalindrome(String s) { int left = 0, right = s.length() - 1; while (left \u0026lt; right) { while (left \u0026lt; s.length() \u0026amp;\u0026amp; Character.isLetterOrDigit(s.charAt(left)) == false) left += 1; while (right \u0026gt;= 0 \u0026amp;\u0026amp; Character.isLetterOfDigit(s.charAt(right)) == false) right -= 1; if (left \u0026gt;= right) return true; if (Character.toLowerCase(s.charAt(left++)) != Character.toLowerCase(s.charAt(right--))) return false; } return true; } } "},{"id":54,"href":"/docs/codes/0100-to-0199/0136.-Single-Number/","title":"0136. Single Number","section":"0100 to 0199","content":" 0136. Single Number # 题目 # 给定一个 非空 整数数组 nums,除了某个元素只出现一次之外,其余每个元素均出现两次。找出那个只出现了一次的元素。\n设计并实现线性时间复杂度的算法来解决此问题,且算法只使用常量额外空间。\n思路 # x ^ x = 0、 x ^ 0 = x\n代码 # class Solution { public int singleNumber(int[] nums) { int result = 0; for (int num: nums) result = result ^ num; return result; } } "},{"id":55,"href":"/docs/codes/0100-to-0199/0137.-Single-Number-ii/","title":"0137. Single Number Ii","section":"0100 to 0199","content":" 137. Single Number ii # 题目 # 给定整数数组 nums,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次。找出并返回只出现了一次的元素。\n设计并实现线性时间复杂度的算法来解决此问题,且算法只使用常量额外空间。\n思路 # 位数统计 代码 # class Solution { public int singleNumber(int[] nums) { int[] count = new int[32]; for (int num: nums) { for (int i = 0; i \u0026lt; 32; i++) { if (((num \u0026gt;\u0026gt; i) \u0026amp; 1) == 1) count[i] += 1; } } int ans = 0; for (int i = 0; i \u0026lt; 32; i++) { if (count[i] % 3 == 1) ans ^= (1 \u0026lt;\u0026lt; i); } return ans; } } 致谢 # 宫水三叶\n"},{"id":56,"href":"/docs/codes/0100-to-0199/0138.-Copy-List-with-Random-Pointer/","title":"0138. Copy List With Random Pointer","section":"0100 to 0199","content":" 0138. 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":57,"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":58,"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":59,"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":60,"href":"/docs/codes/0100-to-0199/0144.-Binary-Tree-Preorder-Traversal/","title":"0144. Binary Tree Preorder Traversal","section":"0100 to 0199","content":" 144. Binary Tree Preorder Traversal # 题目 # 给定二叉树的根节点 root,返回它节点值的 前序 遍历。\n思路 # 代码 # 暴力解 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public void traversal(TreeNode root, List\u0026lt;Integer\u0026gt; ans) { if (root == null) return; ans.add(root.val); traverse(root.left, ans); traverse(root.right, ans); } public List\u0026lt;Integer\u0026gt; preorderTraversal(TreeNode root) { List\u0026lt;Integer\u0026gt; ans = new ArrayList\u0026lt;\u0026gt;(); traverse(root, ans); return ans; } } "},{"id":61,"href":"/docs/codes/0100-to-0199/0145.-Binary-Tree-Postorder-Traversal/","title":"0145. Binary Tree Postorder Traversal","section":"0100 to 0199","content":" 145. Binary Tree Postorder Traversal # 题目 # 给定二叉树的根节点 root,返回它节点值的 后序 遍历。\n思路 # 代码 # 暴力解 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public void traversal(TreeNode root, List\u0026lt;Integer\u0026gt; ans) { if (root == null) return; traverse(root.left, ans); traverse(root.right, ans); ans.add(root.val); } public List\u0026lt;Integer\u0026gt; postorderTraversal(TreeNode root) { List\u0026lt;Integer\u0026gt; ans = new ArrayList\u0026lt;\u0026gt;(); traverse(root, ans); return ans; } } "},{"id":62,"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":63,"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":64,"href":"/docs/codes/0100-to-0199/0148.-Sort-List/","title":"0148. Sort List","section":"0100 to 0199","content":" 148. Sort 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 mergeTwoLists(ListNode headA, ListNode headB) { if (headA == null) return headB; if (headB == null) return headA; ListNode sentinel = new ListNode(-1, null); ListNode ptr = sentinel; while (headA != null \u0026amp;\u0026amp; headB != null) { if (headA.val \u0026lt; headB.val) { ptr = ptr.next = headA; headA = headA.next; } else { ptr = ptr.next = headB; headB = headB.next; } } ptr.next = headA == null ? headB : headA; return sentinel.next; } public ListNode locateMiddle(ListNode head) { if (head == null || head.next == null) return 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; } return slow; } public ListNode sortList(ListNode head) { if (head == null || head.next == null) return head; ListNode ptr = locateMiddle(head); ListNode headNew = ptr.next; ptr.next = null; return mergeTwoLists(sortList(head), sortList(headNew)); } } 致谢 # halfrost\n"},{"id":65,"href":"/docs/codes/0100-to-0199/0150.-Evaluate-Reverse-Polish-Notation/","title":"0150. Evaluate Reverse Polish Notation","section":"0100 to 0199","content":" 0150. Evaluate Reverse Polish Notation # 题目 # 给定字符串数组 tokens,表示一个根据 逆波兰表示法 表示的算术表达式。\n返回表达式的值。\n注意:\n有效的算符为 '+'、'-'、'*' 和 '/' 。 每个操作数(运算对象)都可以是一个整数或者另一个表达式。 两个整数之间的除法总是 向零截断 。 表达式中不含除零运算。 输入是一个根据逆波兰表示法表示的算术表达式。 答案及所有中间计算结果可以用 32 位 整数表示。 思路 # 逆波兰表达式主要有以下两个优点: 去掉括号后表达式无歧义。 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中 代码 # class Solution { public int evalRPN(String[] tokens) { Stack\u0026lt;Integer\u0026gt; stack = new Stack\u0026lt;\u0026gt;(); for(String token: tokens) { switch (token) { case \u0026#34;+\u0026#34; : stack.push(stack.pop() + stack.pop()); break; case \u0026#34;-\u0026#34; : int operand_2 = stack.pop(), operand_1 = stack.pop(); stack.push(operand_1 - operand_2); break; case \u0026#34;*\u0026#34;: stack.push(stack.pop() * stack.pop()); break; case \u0026#34;/\u0026#34;: operand_2 = stack.pop(); operand_1 = stack.pop(); stack.push(operand_1 / operand_2); break; default: stack.push(Integer.parseInt(token)); } } return stack.pop(); } } "},{"id":66,"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":67,"href":"/docs/codes/0100-to-0199/0167.-Two-Sum-II-Input-Array-Is-Sorted/","title":"0167. Two Sum Ii Input Array Is Sorted","section":"0100 to 0199","content":" 0167. Two Sum II - Input Array Is Sorted # 题目 # 给定一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 从数组中找出满足相加之和等于目标数 target 的两个数的下标。 如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 \u0026lt;= index1 \u0026lt; index2 \u0026lt;= numbers.length 。 以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。 假设每个输入 只对应唯一的答案 ,且 不可以 重复使用相同的元素。 所设计的解决方案必须只使用常量级的额外空间。 思路 # 双指针 # 代码 # 双指针 # class Solution { public int[] twoSum(int[] numbers, int target) { int[] ans = new int[2]; int left = 0, right = numbers.length - 1; while (left \u0026lt; right) { if (numbers[left] + numbers[right] \u0026gt; target) right -= 1; else if (numbers[left] + numbers[right] \u0026lt; target) left += 1; else { ans[0] = left + 1; ans[1] = right - 1; break; } } return ans; } } "},{"id":68,"href":"/docs/codes/0100-to-0199/0169.-Majority-Element/","title":"0169. Majority Element","section":"0100 to 0199","content":" 169. Majority Element # 题目 # 给定一个大小为 n 的数组 nums,返回其中的多数元素。多数元素是指在数组中出现次数 大于 n/2 的元素。\n假定数组非空,且给定的数组总是存在多数元素。\n思路 # 摩尔投票法 代码 # class Solution { public int majorityElement(int[] nums) { int major = -1, count = 0; for (int num: nums) { if (count == 0) { major = num; count = 1; } else if (major == num) { count += 1; } else count -= 1; } return major; } } 致谢 # 田野吹吹风\n"},{"id":69,"href":"/docs/codes/0100-to-0199/0189.-Rotate-Array/","title":"0189. Rotate Array","section":"0100 to 0199","content":" 0189. Rotate Array # 题目 # 给定数组 nums,将数组中的元素向右轮转 k 个位置,k 为非负整数。 思路 # 翻转数组 # # visualization (k = 3) nums = \u0026#34;----\u0026gt;--\u0026gt;\u0026#34; result = \u0026#34;--\u0026gt;----\u0026gt;\u0026#34; reverse \u0026#34;----\u0026gt;--\u0026gt;\u0026#34; to \u0026#34;\u0026lt;--\u0026lt;----\u0026#34; reverse \u0026#34;\u0026lt;--\u0026#34; to \u0026#34;--\u0026gt;\u0026#34; reverse \u0026#34;\u0026lt;----\u0026#34; to \u0026#34;----\u0026gt;\u0026#34; finally get \u0026#34;--\u0026gt;----\u0026gt;\u0026#34; 代码 # 翻转数组 # public class Solution { public int hamingWeight(int n) { int numOnes = 0; for (int i = 31; i \u0026gt;= 0; i--) { if ( ((n \u0026gt;\u0026gt; i) \u0026amp; 1) == 1 ) numOnes += 1; } return numOnes;s } } 致谢 # 力扣官方题解\n"},{"id":70,"href":"/docs/codes/0100-to-0199/0191.-Number-of-1-Bits/","title":"0191. Number of 1 Bits","section":"0100 to 0199","content":" 0191. Number of 1 Bits # 题目 # 编写一个函数,输入是一个无符号整数 (以二进制串的形式),返回其二进制表达式中数字位数位 '1' 的个数,也称为 汉明重量。\n在 Java 中,整数的表示有以下两个特点:\n没有无符号整数类型,输入和输出都将被指定为有符号整数类型。 编译器使用 二进制补码 表示有符号整数。 思路 # 代码 # public class Solution { public int hamingWeight(int n) { int numOnes = 0; for (int i = 31; i \u0026gt;= 0; i--) { if ( ((n \u0026gt;\u0026gt; i) \u0026amp; 1) == 1 ) numOnes += 1; } return numOnes;s } } "},{"id":71,"href":"/docs/codes/0100-to-0199/0198.-House-Robber/","title":"0198. House Robber","section":"0100 to 0199","content":" 0198. House Robber # 题目 # 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路 # 动态规划 # 代码 # 动态规划 # class Solution { public int rob(int[] nums) { int[] profits = new int[nums.length]; int ans = 1; for (int i = 0; i \u0026lt; nums.length; i++) { if (i == 0) profits[i] = nums[0]; else if (i == 1) profits[i] = Math.max(nums[0], nums[1]); else profits[i] = Math.max(profits[i-2] + nums[i], profits[i - 1]); ans = Math.max(profits[i], ans); } return ans; } } 致谢 # krahets\n"},{"id":72,"href":"/docs/codes/0100-to-0199/0199.-Binary-Tree-Right-Side-View/","title":"0199. Binary Tree Right Side View","section":"0100 to 0199","content":" 199. Binary Tree Right Side View # 题目 # 给定一个二叉树的 根节点 root,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。\n思路 # 代码 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public List\u0026lt;Integer\u0026gt; rightSideView(TreeNode root) { List\u0026lt;Integer\u0026gt; ans = new LinkedList\u0026lt;\u0026gt;(); if (root == null) return ans; Queue\u0026lt;TreeNode\u0026gt; queue = new LinkedList\u0026lt;\u0026gt;(); queue.offer(root); while (queue.size() != 0) { int layerSize = queue.size(); TreeNode node = null for (int i = 0; i \u0026lt; layerSize; i++) { node = queue.poll(); if (node.left != null) queue.offer(node.left); if (node.right != null) queue.offer(node.right); } ans.add(node.val); } return ans; } } "},{"id":73,"href":"/docs/codes/0200-to-0299/0202.-Happy-Number/","title":"0202. Happy Number","section":"0200 to 0299","content":" 202. Happe Number # 题目 # 判断一个数 n 是否为快乐数。是快乐数则返回 true,否则返回 false。\n「快乐数」 定义为:\n对于一个正整数,每一次将该数替换为它每个位置上数字的平方和。 重复这个过程直至这个数变为 1,也可能是 无限循环 但始终变不到 1。 如果这个过程 结果为1,那么这个数就是快乐数。 思路 # 题目中声明,该过程有两种情况:「该数最终变为1」,「该数进入无限循环,变不到1」。\n如果这句话有所关注,就比较容易地想到用哈希集合解决该问题。\n否则将需要思考快乐数的演化情况,演化情况可参考 力扣官方题解。\n代码 # class Solution { public boolean isHappy(int n) { Set\u0026lt;Integer\u0026gt; set = new HashSet\u0026lt;\u0026gt;(); while (n != 1) { if (set.contains(n) == true) return false; set.add(n); int new Number = 0; while (n != 0) { newNumber += Math.pow(n%10, 2); n /= 10; } n = newNumber; } return true; } } "},{"id":74,"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思路 # 代码 # class Solution { public void moveZeros(int[] nums) { int slow = 0, fast = 0; while (fast \u0026lt; nums.length) { if (nums[fast] != 0) nums[slow++] = nums[fast]; fast += 1; } while (slow \u0026lt; nums.length) nums[slow++] = 0; } } "},{"id":75,"href":"/docs/codes/0200-to-0299/0205.-Isomorphic-Strings/","title":"0205. Isomorphic Strings","section":"0200 to 0299","content":" 0205. Isomorphic Strings # 题目 # 给定两个字符串 s 和 t ,判断它们是否是同构的。 如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。 要求每个出现的字符都映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。 思路 # 哈希 # 代码 # 哈希 # class Solution { public boolean isIsomorphic(String s, String t) { if (s.length() != t.length()) return false; Map\u0026lt;Character, Character\u0026gt; map = new HashMap\u0026lt;\u0026gt;(); for (int i = 0; i \u0026lt; s.length(); i++) { if (map.containsKey(s.charAt(i)) \u0026amp;\u0026amp; map.get(s.charAt(i)) != t.charAt(i)) return false; if (map.containsKey(s.charAt(i)) == false \u0026amp;\u0026amp; map.contains(t.charAt(i))) return false; map.put(s.charAt(i), t.charAt(i)); } return true; } } 致谢 # Krahets\n"},{"id":76,"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":77,"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":78,"href":"/docs/codes/0200-to-0299/0217.-Contains-Duplicate/","title":"0217. Contains Duplicate","section":"0200 to 0299","content":" 0217. Contains Duplicate # 题目 # 给定整数数组 nums 。 若存在出现 至少两次 的元素,返回 true ;否则返回 false 。 思路 # 哈希 # 代码 # 哈希 # class Solution { public boolean containsDuplicate(int[] nums) { Set\u0026lt;Integer\u0026gt; set = new HashSet\u0026lt;\u0026gt;(); for (int num: nums) if (set.contains(num) == true) return true; else set.add(num); return false; } } "},{"id":79,"href":"/docs/codes/0200-to-0299/0219.-Contains-Duplicate-ii/","title":"0219. Contains Duplicate Ii","section":"0200 to 0299","content":" 0219. Contains Duplicate ii # 题目 # 给你一个整数数组 nums 和一个整数 k 判断数组中是否存在两个 不同的索引 i 和 j ,满足 nums[i] == nums[j] 且 abs(i - j) \u0026lt;= k 。 如果存在,返回 true ;否则,返回 false 。 思路 # 滑窗+哈希 # 代码 # 滑窗+哈希 # class Solution { public boolean containsNearbyDuplicate(int[] nums, int k) { Set\u0026lt;Integer\u0026gt; set = new HashSet\u0026lt;\u0026gt;(); for (int i = 0; i \u0026lt; nums.length; i++) { if (i \u0026gt; k) set.remove(nums[i - k - 1]); if (set.contains(nums[i]) == true) return true; set.add(nums[i]); } return false; } } 致谢 # 宫水三叶\n"},{"id":80,"href":"/docs/codes/0200-to-0299/0226.-Invert-Binary-Tree/","title":"0226. Invert Binary Tree","section":"0200 to 0299","content":" 226. Invert Binary Tree # 题目 # 给定二叉树的根节点 root,翻转这棵二叉树,并返回其根节点。\n思路 # 代码 # 递归 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public TreeNode invertTree(TreeNode root) { if (root == null || (root.left == null \u0026amp;\u0026amp; root.right == null)) return root; invertTree(root.left); invertTree(root.right); TreeNode ptr = root.left; root.left = root.right; root.right = ptr; return root; } } "},{"id":81,"href":"/docs/codes/0200-to-0299/0231.-Power-of-Two/","title":"0231. Power of Two","section":"0200 to 0299","content":" 231. Power of Two # 题目 # 给定一个整数 n,判断该整数是否是 2的幂次方。如果是,返回 true;否则,返回 false。\n如果存在一个整数 x 使得 n == 2^x,则认为 n 是 2 的幂次方。\n思路 # 对于数字 2^x,当且仅当加数不小于 2^x 时,和才不小于 2^(x+1) 若 n 的二进制表示中存在不止一个 1,则该整数不是 2 的幂次方。 代码 # 较繁琐的实现 # class Solution { public boolean isPowerOfTwo(int n) { if (n \u0026lt;= 0) return false; boolean flag = false; for (int i = 31; i \u0026gt;= 0; i--) { if (((n \u0026gt;\u0026gt; i) \u0026amp; 1) == 1) { if (flag == false) flag = true; else return false; } } return true; } } 利用位运算简化代码 # class Solution { public boolean isPowerOfTwo(int n) { return n \u0026gt; 0 \u0026amp;\u0026amp; (n \u0026amp; n-1) == 0;s } } 致谢 # Krahets\n"},{"id":82,"href":"/docs/codes/0200-to-0299/0232.-Implement-Queue-using-Stacks/","title":"0232. Implement Queue Using Stacks","section":"0200 to 0299","content":" 0255. Implement Queue using Stacks # 题目 # 使用两个栈实现一个先入先出的栈,支持普通队列的全部四种操作。 实现 MyQueue 类: void push(int x) 将元素 x 推到队列的末尾 int pop() 从队列的开头移除并返回元素 int peek() 返回队列开头的元素 boolean empty() 如果队列为空,返回 true;否则,返回 false 思路 # 使用两个栈实现队列 # 代码 # 使用两个栈实现队列 # class MyQueue { Stack\u0026lt;Integer\u0026gt; inStack, outStack; public MyQueue() { this.inStack = new Stack\u0026lt;\u0026gt;(); this.outStack = new Stack\u0026lt;\u0026gt;(); } public void push(int x) { this.inStack.push(x); } public int pop() { if (this.outStack.size() == 0) { while (this.inStack.size() != 0) { this.outStack.push(this.inStack.pop()); } } return this.outStack.pop(); } public int peek() { if (this.outStack.size() == 0) { while (this.inStack.size() != 0) { this.outStack.push(this.inStack.pop()); } } return this.outStack.peek(); } public boolean empty() { return this.outStack.size() == 0 \u0026amp;\u0026amp; this.inStack.size() == 0; } } 致谢 # 力扣官方题解\n"},{"id":83,"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":84,"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":85,"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":86,"href":"/docs/codes/0200-to-0299/0255.-Implement-Stack-using-Queues/","title":"0255. Implement Stack Using Queues","section":"0200 to 0299","content":" 0255. Implement Stack using Queues # 题目 # 使用两个队列实现一个后入先出的栈,支持普通栈的全部四种操作。 实现 MyStack 类: void push(int x) 将元素 x 压入栈顶。 int pop() 移除并返回栈顶元素。 int top() 返回栈顶元素。 boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。 思路 # 使用两个队列实现栈 # 代码 # 使用两个队列实现栈 # class MyStack { private Queue\u0026lt;Integer\u0026gt; stack, queue; public MyStack() { this.stack = new LinkedList\u0026lt;\u0026gt;(); this.queue = new LinkedList\u0026lt;\u0026gt;(); } public void push(int x) { if (this.stack.size() == 0) this.stack.offer(x); else { this.queue.offer(x); while (this.stack.size() != 0) this.queue.offer(this.stack.poll()); Queue\u0026lt;Integer\u0026gt; temp = this.stack; this.stack = this.queue; this.queue = temp; } } public int pop() { return this.stack.poll(); } public int top() { return this.stack.peek(); } public boolean empty() { return this.stack.size() == 0; } } "},{"id":87,"href":"/docs/codes/0200-to-0299/0263.-Ugly-Number/","title":"0263. Ugly Number","section":"0200 to 0299","content":" 263. Ugly Number # 题目 # 丑数 是只包含质因数 2、3 和 5 的正整数。\n给你一个整数 n ,请你判断 n 是否为 丑数 。如果是,返回 true ;否则,返回 false 。\n-2^31 \u0026lt;= n \u0026lt;= 2^31 - 1\n思路 # 模拟 # 代码 # 模拟 # class Solution { public boolean isUgly(int n) { if (n \u0026lt;= 0) return false; while (n % 2 == 0) n /= 2; while (n % 3 == 0) n /= 3; while (n % 5 == 0) n /= 5; return n == 1; } } "},{"id":88,"href":"/docs/codes/0200-to-0299/0268.-Missing-Number/","title":"0268. Missing Number","section":"0200 to 0299","content":" 268. Missing Number # 题目 # 给定一个包含 [0, n] 中 n 个数的数组 nums,找出 [0, n] 这个范围内没有出现在数组中的那个数。\n思路 # 数学: expectSum - actualSum 异或: x ^ x = 0,expect ^ actual 原地哈希: :question: 代码 # 数学 # class Solution { public int missingNumber(int[] nums) { int n = nums.length; int expected = n * (n + 1) / 2; int actual = 0; for (int num: nums) actual += num; return exptected - actual; } } 异或 # class Solution { public int missingNumber(int[] nums) { int whole = 0; for (int i = 0; i \u0026lt; nums.length + 1; i++) whole = whole ^ i; for (int num: nums) whole = whole ^ num; return whole; } } 致谢 # 宫水三叶\n"},{"id":89,"href":"/docs/codes/0200-to-0299/0278.-First-Bad-Version/","title":"0278. First Bad Version","section":"0200 to 0299","content":" 0035. Search Insert Position # 题目 # 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。 如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 使用时间复杂度为 O(log n) 的算法。 思路 # 二分查找(左闭右开) # 令右指针指向已知大于目标值的最靠前位置,左指针指向已知不大于目标值的最靠后位置 当两指针相遇,所指向位置为元素的插入位置 代码 # 二分查找(左闭右开) # class Solution { public int searchInsert(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 right; } } "},{"id":90,"href":"/docs/codes/0200-to-0299/0283.-Move-Zeros/","title":"0283. Move Zeros","section":"0200 to 0299","content":" 0283. Move Zeros # 题目 # 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末位,同时保持非零元素的相对顺序。\n必须在不复制数组的情况下原地对数组进行操作。\n思路 # 代码 # class Solution { public void moveZeros(int[] nums) { int slow = 0, fast = 0; while (fast \u0026lt; nums.length) { if (nums[fast] != 0) nums[slow++] = nums[fast]; fast++; } while (slow \u0026lt; nums.length) nums[slow++] = 0; } } "},{"id":91,"href":"/docs/codes/0200-to-0299/0290.-Word-Pattern/","title":"0290. Word Pattern","section":"0200 to 0299","content":" 0290. Word Pattern # 题目 # 给定一种规律 pattern 和一个字符串 s ,判断 s 是否遵循相同的规律。 这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接的对应规律。 思路 # 哈希 # 代码 # 哈希 # class Solution { public boolean wordPattern(String pattern, String s) { String[] words = s.split(\u0026#34; \u0026#34;); if (pattern.length() != words.length) return false; Map\u0026lt;Character, String\u0026gt; map = new HashMap\u0026lt;\u0026gt;(); for (int i = 0; i \u0026lt; pattern.length(); i++) { char pat = pattern.charAt(i); String word = words[i]; if (map.contains(pat) \u0026amp;\u0026amp; map.get(pat).equals(word) == false) return false; else if (map.contains(pat) == false \u0026amp;\u0026amp; map.containsValue(word)) return false; map.put(pat, word); } return true; } } 致谢 # 沉默王二\n"},{"id":92,"href":"/docs/codes/0200-to-0299/0292.-Nim-Game/","title":"0292. Nim Game","section":"0200 to 0299","content":" 0292. Nim Game # 题目 # 两人玩 Nim 游戏\n桌子上有一堆石头。\n每一回合,轮到的人拿掉 1 - 3 块石头。\n拿掉最后一块石头的人就是获胜者。\n假设两人所走每一步都是最优解。\n编写函数,判断先手能否在给定石头数量为 n 的情况下赢得游戏。\n思路 # 博弈 # 若 n 不是 4 的幂,则在每回合先手总可以令后手面对总数为 4的若干次幂 的石头,直至令后手面对 4块石头。此时先手必胜。 同理,若 n 是 4 的幂,则先手必败。 代码 # 博弈 # class Solution { public boolean canWinNim(int n) { return n % 4 != 0; } } "},{"id":93,"href":"/docs/codes/0300-to-0399/0326.-Power-of-Three/","title":"0326. Power of Three","section":"0300 to 0399","content":" 0326. Power of Three # 题目 # 给定整数 n,判断它是否为 3 的幂次方。 -2^31 \u0026lt;= n \u0026lt;= 2^31 - 1 思路 # 素因数分解 + 考虑输入范围 # 1162261467 是输入范围 -2^31 \u0026lt;= n \u0026lt;= 2^31 - 1 内最大的 3 的幂次方。 只需判断 n 能否整除 1162261467 即可得知它是否为 3 的幂次方。 1162261467 该值可以通过循环来确定。 代码 # 素因数分解 + 考虑输入范围 # class Solution { public boolean isPowerOfThree(int n) { if (n \u0026lt;= 0) return false; return 1162261467 % n == 0; } } 致谢 # 宫水三叶\n"},{"id":94,"href":"/docs/codes/0300-to-0399/0328.-Odd-Even-Linked-List/","title":"0328. Odd Even Linked List","section":"0300 to 0399","content":" 0328. 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":95,"href":"/docs/codes/0300-to-0399/0338.-Counting-Bits/","title":"0338. Counting Bits","section":"0300 to 0399","content":" 338. Counting Bits # 题目 # 给定一个整数 n,对于 0 \u0026lt;= i \u0026lt;= n 中的每个 i,计算其二进制表示中 1 的个数,返回一个长度为 n+1 的数组 ans 作为答案。\n思路 # 右移计数 Brian Kernighan 代码 # 右移计数 # class Solution { public int count(int num) { int result = 0; for (int i = 30; i \u0026gt;= 0; i--) { if (((num \u0026gt;\u0026gt; i) \u0026amp; 1) == 1) result += 1; } return result; } public int[] countBits(int n) { int[] ans = new int[n + 1]; for (int i = 0; i \u0026lt;= n; i++) { ans[i] = count(i); } return ans; } } Brian Kernighan # class Solution { public int count(int num) { int ans = 0; while (num \u0026gt; 0) { num \u0026amp;= num - 1; ans += 1; } return ans; } public int[] countBits(int n) { int[] ans = new int[n + 1]; for(int i = 0; i \u0026lt;= n; i++) ans[i] = count(i); return ans; } } "},{"id":96,"href":"/docs/codes/0300-to-0399/0342.-Power-of-Four/","title":"0342. Power of Four","section":"0300 to 0399","content":" 342. Power of Four # 题目 # 给定一个整数,判断它是否是 4 的幂次方。\n思路 # 某个整数是 4 的幂次需要满足三个条件:\n正数 二进制表示中只含有一位 1 二进制表示中最高位 1 所在比特位为偶数 代码 # class Solution { public boolean isPowerOfFour(int n) { if (n \u0026lt;= 0) return false; boolean found = false; for (int i = 31; i \u0026gt;= 0; i--) { if (((n \u0026gt;\u0026gt; i) \u0026amp; 1) == 1) { if ((i \u0026amp; 1) == 1 || found == true) return false; found = true; } } return true; } } "},{"id":97,"href":"/docs/codes/0300-to-0399/0344.-Reverse-String/","title":"0344. Reverse String","section":"0300 to 0399","content":" 0344. Reverse String # 题目 # 编写一个函数,将输入的字符串翻转过来。字符串以字符数组 s 的形式给出。\n不要给另外的数组分配额外的空间,原地修改输入数组,使用 O(1) 的额外空间解决这一问题。\n思路 # 双指针 # 代码 # 双指针 # class Solution { public void reverseString(char[] s) { for (int i=0, j=s.length-1; i\u0026lt;j; i++, j--) { char temp = s[i]; s[i] = s[j]; s[j] = temp; } } } "},{"id":98,"href":"/docs/codes/0300-to-0399/0345.-Reverse-Vowels-of-a-String/","title":"0345. Reverse Vowels of a String","section":"0300 to 0399","content":" 0345. Reverse Vowels of a String # 题目 # 给定字符串 s,反转其中的所有元素字母,并返回字符串。 元音字母包含 'a','e','i','o','u' 及其大写形式。 思路 # 双指针 # 代码 # 双指针 (StringBuilder) # class Solution { boolean isVowel(Character ch) { if (ch == \u0026#39;a\u0026#39; || ch == \u0026#39;e\u0026#39; || ch == \u0026#39;i\u0026#39; || ch == \u0026#39;o\u0026#39; || ch == \u0026#39;u\u0026#39;) return true; if (ch == \u0026#39;A\u0026#39; || ch == \u0026#39;E\u0026#39; || ch == \u0026#39;I\u0026#39; || ch == \u0026#39;O\u0026#39; || ch == \u0026#39;U\u0026#39;) return true; return false; } public String reverseVowels(String s) { int i = 0, j = s.length() - 1; StringBuilder sb = new StringBuilder(s); while (i \u0026lt; j) { while (i \u0026lt; j \u0026amp;\u0026amp; isVowel(s.charAt(i)) == false) i += 1; while (i \u0026lt; j \u0026amp;\u0026amp; isVowel(s.charAt(j)) == false) j -= 1; Character ch = s.charAt(i); sb.replace(i, i + 1, String.valueOf(s.charAt(j))); sb.replace(j, j + 1, String.valueOf(ch)); i += 1; j -= 1; } return sb.toString(); } } 双指针(String.toCharArray \u0026amp; String.valueOf) # class Solution { public void swap(char[] charArray, int i, int j) { char ch = charArray[i]; charArray[i] = charArray[j]; charArray[j] = ch; } public String reverseVowels(String s) { char[] vowels = new char[]{\u0026#39;a\u0026#39;, \u0026#39;e\u0026#39;, \u0026#39;i\u0026#39;, \u0026#39;o\u0026#39;, \u0026#39;u\u0026#39;}; boolean[] isVowel = new boolean[128]; for (char vowel: vowels) isVowel[vowel - \u0026#39; \u0026#39;] = isVowel[Character.toUpperCase(vowel) - \u0026#39; \u0026#39;] = true; char[] charArray = s.toCharArray(); int i = 0, j = charArray.length - 1; while (i \u0026lt; j) { if (isVowel[charArray[i] - \u0026#39; \u0026#39;] == true \u0026amp;\u0026amp; isVowel[charArray[j] - \u0026#39; \u0026#39;] == true) swap(charArray, i++, j--); else { if (isVowel[charArray[i] - \u0026#39; \u0026#39;] == false) i += 1; if (isVowel[charArray[j] - \u0026#39; \u0026#39;] == false) j -= 1; } } return String.valueOf(charArray); } } "},{"id":99,"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":100,"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":101,"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":102,"href":"/docs/codes/0300-to-0399/0374.-Guess-Number-Higher-or-Lower/","title":"0374. Guess Number Higher or Lower","section":"0300 to 0399","content":" 0374. Guess Number Higher or Lower # 题目 # 猜数字游戏 规则如下: 从 1 到 n 随机选择一个数字。 猜出被选择的这个数字。 guess 函数会返回所猜数字与所选数字的大小关系。 -1:所选数字小于所猜数字 1:所选数字大于所猜数字 0:所选数字等于所猜数字 返回所选数字。 思路 # 二分 # 代码 # 二分 # /** * Forward declaration of guess API. * @param num your guess * @return -1 if num is higher than the picked number *\t1 if num is lower than the picked number * otherwise return 0 * int guess(int num); */ public class Solution extends GuessGame { public int guessNumber(int n) { int left = 1, right = n; while (left \u0026lt;= right) { int mid = left + (right - left) / 2; if (guess(mid) == 0) return mid; else if (guess(mid) == -1) right = mid - 1; else left = mid + 1; } return -1; } } "},{"id":103,"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":104,"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":105,"href":"/docs/codes/0300-to-0399/0383.-Ransom-Note/","title":"0383. Ransom Note","section":"0300 to 0399","content":" 383. Ransom Note # 题目 # 给定两个字符串: ransomNote 和 magazine,判断 ransomNote 能不能由 magazine 里面的字符构成。\n如果可以,返回 true,否则返回 false。\nmagazine 中的每个字符只能在 ransomNote 中使用一次。\n思路 # 代码 # class Solution { public boolean canConstruct(String ransomNote, String magazine) { if (ransomNote.length() \u0026gt; magazine.length()) return false; int[] count = new int[26]; for(int i=0; i\u0026lt;magazine.length(); i++) count[magazine.charAt(i)-\u0026#39;a\u0026#39;] += 1; for(int i=0; i\u0026lt;ransomNote.length(); i++) { if (count[ransomNote.charAt(i)-\u0026#39;a\u0026#39;] == 0) return false; count[ransomNote.charAt(i)-\u0026#39;a\u0026#39;] -= 1; } return true; } } "},{"id":106,"href":"/docs/codes/0300-to-0399/0387.-First-Unique-Character-in-a-String/","title":"0387. First Unique Character in a String","section":"0300 to 0399","content":" 387. First Unique Character in a String # 题目 # 给定一个字符串 s,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。\n思路 # 代码 # class Solution { public int firstUniqChar(String s) { int[] seen = new int[26]; for (int i = 0; i \u0026lt; s.length(); i++) seen[s.charAt(i) - \u0026#39;a\u0026#39;] += 1; for (int i = 0; i \u0026lt; s.length(); i++) if (seen[s.charAt(i) - \u0026#39;a\u0026#39;] == 1) return i; return -1; } } "},{"id":107,"href":"/docs/codes/0300-to-0399/0389.-Find-the-Difference/","title":"0389. Find the Difference","section":"0300 to 0399","content":" 389. Find the Difference # 题目 # 给定两个字符串 s 和 t,它们只包含小写字母。\n字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。\n找出在 t 中被添加的字母。\n思路 # 代码 # class Solution { public char findTheDifference(String s, String t) { char res = 0; for (int i = 0; i \u0026lt; s.length(); i++) res ^= s.charAt(i); for (int i = 0; i \u0026lt; t.length(); i++) res ^= t.charAt(i); return res; } } "},{"id":108,"href":"/docs/codes/0300-to-0399/0392.-Is-Subsequence/","title":"0392. Is Subsequence","section":"0300 to 0399","content":" 0392. Is Subsequence # 题目 # 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。 (例如,\u0026quot;ace\u0026quot;是\u0026quot;abcde\u0026quot;的一个子序列,而\u0026quot;aec\u0026quot;不是)。 思路 # 代码 # class Solution { public boolean isSubsequence(String s, String t) { int i = 0, j = 0; while (i \u0026lt; s.length() \u0026amp;\u0026amp; j \u0026lt; t.length()) { if (s.charAt(i) == t.charAt(j)) i++; j++; } return i == s.length(); } } "},{"id":109,"href":"/docs/codes/0400-to-0499/0405.-Convert-a-Number-to-Hexadecimal/","title":"0405. Convert a Number to Hexadecimal","section":"0400 to 0499","content":" 0405. Convert a Number to Hexadecimal # 题目 # 给定一个整数,将这个数转换为十六进制数。 对于负整数,通常使用补码运算方式。 十六进制中所有字母(a-f)都必须是小写。 十六进制字符串中不能包含多余的前导零。如果要转化的数为0,那么以单个字符'0'来表示;对于其他情况,十六进制字符串中的第一个字符将不会是0字符。 给定的数确保在32位有符号整数范围内。 不能使用任何由库提供的将数字直接转换或格式化为十六进制的方法。 思路 # 模拟 # 代码 # 模拟 # class Solution { public String int2hex(int num) { switch (num) { case 0x00000000 : return \u0026#34;0\u0026#34;; case 0x10000000 : return \u0026#34;1\u0026#34;; case 0x20000000 : return \u0026#34;2\u0026#34;; case 0x30000000 : return \u0026#34;3\u0026#34;; case 0x40000000 : return \u0026#34;4\u0026#34;; case 0x50000000 : return \u0026#34;5\u0026#34;; case 0x60000000 : return \u0026#34;6\u0026#34;; case 0x70000000 : return \u0026#34;7\u0026#34;; case 0x80000000 : return \u0026#34;8\u0026#34;; case 0x90000000 : return \u0026#34;9\u0026#34;; case 0xa0000000 : return \u0026#34;a\u0026#34;; case 0xb0000000 : return \u0026#34;b\u0026#34;; case 0xc0000000 : return \u0026#34;c\u0026#34;; case 0xd0000000 : return \u0026#34;d\u0026#34;; case 0xe0000000 : return \u0026#34;e\u0026#34;; case 0xf0000000 : return \u0026#34;f\u0026#34;; } return \u0026#34;\u0026#34;; } public String toHex(int num) { if (num == 0) return \u0026#34;0\u0026#34;; boolean flag = false; String ans = \u0026#34;\u0026#34;; for (int i = 0; i \u0026lt; 8; i++) { int and = num \u0026amp; 0xf0000000; if (and != 0) flag = true; if (flag) ans += int2hex(num \u0026amp; and); num \u0026lt;\u0026lt;= 4; } return ans; } } 致谢 # 宫水三叶\n"},{"id":110,"href":"/docs/codes/0400-to-0499/0412.-Fizz-Buzz/","title":"0412. Fizz Buzz","section":"0400 to 0499","content":" 0412. Fizz Buzz # 题目 # 给定整数 n ,找出 1 至 n 各个整数的 Fizz Buzz 表示,并用字符串数组 answer(下标从 1 开始)返回结果,其中:\nanswer[i] == \u0026quot;FizzBuzz\u0026quot; 如果 i 同时是 3 和 5 的倍数。\nanswer[i] == \u0026quot;Fizz\u0026quot; 如果 i 是 3 的倍数。\nanswer[i] == \u0026quot;Buzz\u0026quot; 如果 i 是 5 的倍数。\nanswer[i] == i (以字符串形式)如果上述条件全不满足。\n思路 # 模拟 # 代码 # 模拟 # class Solution { public List\u0026lt;String\u0026gt; fizzBuzz(int n) { List\u0026lt;String\u0026gt; ans = new LinkedList\u0026lt;\u0026gt;(); for (int i = 1; i \u0026lt;= n; i++) { if (i % 3 == 0 \u0026amp;\u0026amp; i % 5 == 0) ans.add(\u0026#34;FizzBuzz\u0026#34;); else if (i % 3 == 0) ans.add(\u0026#34;Fizz\u0026#34;); else if (i % 5 == 0) ans.add(\u0026#34;Buzz\u0026#34;); else ans.add(Integer.toString(i)); } return ans; } } "},{"id":111,"href":"/docs/codes/0400-to-0499/0414.-Third-Maximum-Number/","title":"0414. Third Maximum Number","section":"0400 to 0499","content":" 0414. Third Maximum Number # 题目 # 给定一个非空数组,返回该数组中 第三大的数。 如果不存在,则返回数组中最大的数。 注: 要求返回第三大的数,是指在所有不同数字中排第三大的数。 思路 # 模拟 + 哈希 # 代码 # 模拟 + 哈希 # class Solution { public int thirdMax(int[] nums) { Set\u0026lt;Integer\u0026gt; set = new HashSet\u0026lt;\u0026gt;(); int first = Integer.MIN_VALUE, second = Integer.MIN_VALUE, third = Integer.MIN_VALUE; for (int num: nums) { if (set.contains(num) == false) { if (set.size() == 0) first = num; else if (set.size() == 1) { second = first \u0026gt; num ? num : first; first = first \u0026gt; num ? first : num; } else if (set.size() == 2) { if (num \u0026gt; first) { third = second; second = first; first = num; } else if (num \u0026gt; second) { third = second; second = num; } else third = num; } else { if (num \u0026gt; first) { third = second; second = first; first = num; } else if (num \u0026gt; second) { third = second; second = num; } else if (num \u0026gt; third) { third = num; } } set.add(num); } } return set.size() \u0026gt; 2 ? third : first; } } 模拟 # class Solution { public int thirdMax(int[] nums) { long first = Long.MIN_VALUE, second = Long.MIN_VALUE, third = Long.MIN_VALUE; for (int num: nums) { if (num \u0026gt; first) { third = second; second = first; first = num; } else if (first \u0026gt; num \u0026amp;\u0026amp; num \u0026gt; second) { third = second; second = num; } else if (second \u0026gt; num \u0026amp;\u0026amp; num \u0026gt; third) third = num; } return third == Long.MIN_VALUE ? (int)first : (int)third; } } "},{"id":112,"href":"/docs/codes/0400-to-0499/0429.-N-ary-Tree-Level-Order-Traversal/","title":"0429. N Ary Tree Level Order Traversal","section":"0400 to 0499","content":" 0429. N-ary Tree Level Order Traversal # 题目 # 给定一个 N 叉树,返回其节点的 层序遍历。\n思路 # 代码 # class Node { public int val; public List\u0026lt;Node\u0026gt; children; public Node() {} public Node(int _val) { val = _val; } public Node(int _val, List\u0026lt;Node\u0026gt; _children) { val = _val; children = _ children; } } class Solution { public List\u0026lt;List\u0026lt;Integer\u0026gt;\u0026gt; levelOrder(Node root) { List\u0026lt;List\u0026lt;Integer\u0026gt;\u0026gt; ans = new LinkedList\u0026lt;\u0026gt;(); if (root == null) return ans; Queue\u0026lt;Node\u0026gt; queue = new LinkedList\u0026lt;\u0026gt;(); queue.offer(root); while (queue.isEmpty() == false) { int layerSize = queue.size(); ans.add(new LinkedList\u0026lt;\u0026gt;()); for (int i = 0; i \u0026lt; layerSize; i++) { Node node = queue.poll(); ans.get(ans.size() - 1).add(node.val); for (Node child: node.children) queue.offer(child); } } return ans; } } "},{"id":113,"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":114,"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":115,"href":"/docs/codes/0400-to-0499/0434.-Number-of-Segments-in-a-String/","title":"0434. Number of Segments in a String","section":"0400 to 0499","content":" 0434. Number of Segments in a String # 题目 # 统计字符串中的单词个数,这里的单词指的是连续的非空格的字符。 假定字符串不包括任何不可打印的字符。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int countSegments(String s) { if (s.length() == 0) return 0; int ans = s.charAt(0) == \u0026#39; \u0026#39; ? 0 : 1, ptr = 0; while (ptr \u0026lt; s.length() - 1) { if (s.charAt(ptr) == \u0026#39; \u0026#39; \u0026amp;\u0026amp; s.charAt(ptr + 1) != \u0026#39; \u0026#39;) { ans++; ptr += 2; } else ptr++; } return ans; } } "},{"id":116,"href":"/docs/codes/0400-to-0499/0441.-Arranging-Coins/","title":"0441. Arranging Coins","section":"0400 to 0499","content":" 0441. Arranging Coins # 题目 # 共有 n 枚硬币,将它们按阶梯状排列。 对于一个由 k 行组成的阶梯,其第 i 行必须正好有 i 枚硬币。阶梯的最后一行 可能 是不完整的。 给定数字 n,计算并返回可形成 完整阶梯行 的总行数。 1 \u0026lt;= n \u0026lt;= 2^31 - 1 思路 # 二分查找 # 代码 # 二分查找 # class Solution { public long capacity(int k) { return (long) k * (k + 1) / 2; } public int arrangeCoins(int n) { /** left 表示已知能填充满的最大行数, right 是已知不能填充满的最小行数 */ int left = 1, right = n; while (left \u0026lt; right - 1) { int mid = left + (right - left) / 2; if (capacity(mid) == n) return mid; else if (capacity(mid) \u0026gt; n) right = mid; else left = mid; } return left; } } "},{"id":117,"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":118,"href":"/docs/codes/0400-to-0499/0448.-Find-All-Numbers-Disappeared-in-an-Arry/","title":"0448. Find All Numbers Disappeared in an Arry","section":"0400 to 0499","content":" 0448. Find All Numbers Disappeared in an Array # 题目 # 给定一个含 n 个整数的数组 nums,其中 nums[i] 在区间 [1, n] 内。找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。\n思路 # 原地哈希 代码 # class Solution { public List\u0026lt;Integer\u0026gt; findDisappearedNumbers(int[] nums) { for (int num: nums) { if (nums[Math.abs(num) - 1] \u0026gt; 0) nums[Math.abs(num) - 1] *= -1; } List\u0026lt;Integer\u0026gt; ans = new LinkedList\u0026lt;\u0026gt;(); for (int i = 0; i \u0026lt; nums.length; i++) { if (nums[i] \u0026gt; 0) ans.add(i + 1); } return ans; } } 致谢 # 负雪明烛\n"},{"id":119,"href":"/docs/codes/0400-to-0499/0455.-Assign-Cookies/","title":"0455. Assign Cookies","section":"0400 to 0499","content":" 0455. Assign Cookies # 题目 # 为孩子们分配饼干,每个孩子最多只能给一块饼干。 孩子 i 对应胃口值 g[i]。饼干 j 对应尺寸 s[j]。若 s[j] \u0026gt;= g[i],则饼干 j 可以令孩子 i 满足。 尽可能满足最多数量的孩子,并返回这个最大数值。 思路 # 排序+双指针+贪心 代码 # 排序+双指针+贪心 # class Solution { public int findContentChildren(int[] g, int[] s) { Arrays.sort(g); Arrays.sort(s); int i = 0, j = 0; while (i \u0026lt; g.length \u0026amp;\u0026amp; j \u0026lt; s.length) { while (j \u0026lt; s.length \u0026amp;\u0026amp; g[i] \u0026gt; s[j]) j += 1; if (j++ \u0026lt; s.length) i += 1; } return i; } } "},{"id":120,"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":121,"href":"/docs/codes/0400-to-0499/0461.-Hamming-Distance/","title":"0461. Hamming Distance","section":"0400 to 0499","content":" 461. Hamming Distance # 题目 # 两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。\n给定两个整数 x 和 y,计算并返回它们之间的汉明距离。\n思路 # 异或 + 统计 1 的数目\n代码 # 汉明距离 # class Solution { public int hammingDistance(int x, int y) { int sum = x ^ y; int hammingDistance = 0; for (int i=31; i\u0026gt;=0; i--) { if (((sum \u0026gt;\u0026gt; i) \u0026amp; 1) == 1) hammingDistance += 1; } return hammingDistance; } } "},{"id":122,"href":"/docs/codes/0400-to-0499/0476.-Number-Complement/","title":"0476. Number Complement","section":"0400 to 0499","content":" 476. Number Complement # 题目 # 对整数的二进制表示取反 (0 变 1,1 变 0) 后,再转换为十进制表示,可以得到这个整数的补数。\n如整数 5 的二进制表示是 \u0026quot;101\u0026quot;,取反后得到 \u0026quot;010\u0026quot;,再转回十进制表示得到补数 2。\n给定一个整数,输出其补数。\n注: 1 \u0026lt;= num \u0026lt; 2^31\n思路 # 代码 # class Solution { public int findComplement(int num) { if (num == 0) return 1; boolean flag = false; for (int i = 30; i \u0026gt;= 0; i--) { if (((num \u0026gt;\u0026gt; i) \u0026amp; 1) == 1) flag = true; if (flag == true) { num ^= 1 \u0026lt;\u0026lt; i; } } return num; } } "},{"id":123,"href":"/docs/codes/0400-to-0499/0482.-License-Key-Formatting/","title":"0482. License Key Formatting","section":"0400 to 0499","content":" 0482. License Key Formatting # 题目 # 给定许可密钥字符串 s,仅由字母、数字字符和破折号组成。字字符串由 n 个破折号分成 n+1组。 给定整数 k 以重新格式化字符串,使每一组包含 k 个字符。 第一组可以比 k 短,但仍必须包含至少一个字符。 两组之间需要插入破折号,且应该将所有小写字母转换为大写字母。 思路 # 模拟 # 代码 # 模拟 # class Solution { public String licenseKeyFormatting(String s, int k) { /** 遍历 s, 确定格式化后的密钥长度 */ int numLetterOrDigits = 0; for (int i = 0; i \u0026lt; s.length(); i++) { if (Character.isLetterOrDigit(s.charAt(i))) numLetterOrDigits++; } int sz = numLetterOrDigits; if (sz == 0) return \u0026#34;\u0026#34;; sz += numLetterOrDigits % k == 0 ? numLetterOrDigits / k - 1 : numLetterOrDigits / k; char[] ans = new char[sz]; /** 双指针 */ int ptrS = s.length() - 1, ptrANS = ans.length - 1, cnt = 0; while (ptrS \u0026gt;= 0) { if (cnt == k \u0026amp;\u0026amp; ptrANS \u0026gt; -1) { ans[ptrANS--] = \u0026#39;-\u0026#39;; cnt = 0; } else { char ch = s.charAt(ptrS--); if (Character.isDigit(ch)) { cnt++; ans[ptrANS--] = ch; } else if (Character.isLetter(ch)) { cnt++; ans[ptrANS--] = Character.toUpperCase(ch); } } } return String.valueOf(ans); } } 致谢 # 宫水三叶\n"},{"id":124,"href":"/docs/codes/0400-to-0499/0485.-Max-Consecutive-Ones/","title":"0485. Max Consecutive Ones","section":"0400 to 0499","content":" 0485. Max Consecutive Ones # 题目 # 给定二进制数组 nums,计算其中最大连续 1 的个数。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int findMaxConsecutiveOnes(int[] nums) { int ans = 0, cnt = 0; for (int num: nums) { if (num == 0) cnt = 0; else ans = Math.max(ans, ++cnt); } return ans; } } "},{"id":125,"href":"/docs/codes/0400-to-0499/0495.-Teemo-Attacking/","title":"0495. Teemo Attacking","section":"0400 to 0499","content":" 495. Teemo Attacking # 题目 # 在《英雄联盟》的世界中,有一个叫 “提莫” 的英雄。他的攻击可以让敌方英雄艾希(编者注:寒冰射手)进入中毒状态。\n当提莫攻击艾希,艾希的中毒状态正好持续 duration 秒。\n正式地讲,提莫在 t 发起发起攻击意味着艾希在时间区间 [t, t + duration - 1](含 t 和 t + duration - 1)处于中毒状态。如果提莫在中毒影响结束 前 再次攻击,中毒状态计时器将会 重置 ,在新的攻击之后,中毒影响将会在 duration 秒后结束。\n给你一个 非递减 的整数数组 timeSeries ,其中 timeSeries[i] 表示提莫在 timeSeries[i] 秒时对艾希发起攻击,以及一个表示中毒持续时间的整数 duration 。\n返回艾希处于中毒状态的 总 秒数。\n思路 # 代码 # class Solution { public int findPoisonedDuration(int[] timeSeries, int duration) { int lasting = 0; for (int i = 0; i \u0026lt; timeSeries.length - 1; i++) { lasting += Math.min(duration, timeSeries[i+1]-timeSeries[i]); } lasting += duration; return lasting; } } "},{"id":126,"href":"/docs/codes/0500-to-0599/0500.-Keyboard-Row/","title":"0500. Keyboard Row","section":"0500 to 0599","content":" 0500. Keyboard Row # 题目 # 给定字符串数组 words ,返回可以使用在 美式键盘 同一行的字母打印出来的单词。 美式键盘 中: 第一行由字符 \u0026quot;qwertyuiop\u0026quot; 组成。 第二行由字符 \u0026quot;asdfghjkl\u0026quot; 组成。 第三行由字符 \u0026quot;zxcvbnm\u0026quot; 组成。 思路 # 模拟+打表 # 代码 # 模拟+打表 # class Solution { public void mapping (int[] qwerty) { qwerty[\u0026#39;q\u0026#39;-\u0026#39;a\u0026#39;] = 0; qwerty[\u0026#39;w\u0026#39;-\u0026#39;a\u0026#39;] = 0; qwerty[\u0026#39;e\u0026#39;-\u0026#39;a\u0026#39;] = 0; qwerty[\u0026#39;r\u0026#39;-\u0026#39;a\u0026#39;] = 0; qwerty[\u0026#39;t\u0026#39;-\u0026#39;a\u0026#39;] = 0; qwerty[\u0026#39;y\u0026#39;-\u0026#39;a\u0026#39;] = 0; qwerty[\u0026#39;u\u0026#39;-\u0026#39;a\u0026#39;] = 0; qwerty[\u0026#39;i\u0026#39;-\u0026#39;a\u0026#39;] = 0; qwerty[\u0026#39;o\u0026#39;-\u0026#39;a\u0026#39;] = 0; qwerty[\u0026#39;p\u0026#39;-\u0026#39;a\u0026#39;] = 0; qwerty[\u0026#39;a\u0026#39;-\u0026#39;a\u0026#39;] = 1; qwerty[\u0026#39;s\u0026#39;-\u0026#39;a\u0026#39;] = 1; qwerty[\u0026#39;d\u0026#39;-\u0026#39;a\u0026#39;] = 1; qwerty[\u0026#39;f\u0026#39;-\u0026#39;a\u0026#39;] = 1; qwerty[\u0026#39;g\u0026#39;-\u0026#39;a\u0026#39;] = 1; qwerty[\u0026#39;h\u0026#39;-\u0026#39;a\u0026#39;] = 1; qwerty[\u0026#39;j\u0026#39;-\u0026#39;a\u0026#39;] = 1; qwerty[\u0026#39;k\u0026#39;-\u0026#39;a\u0026#39;] = 1; qwerty[\u0026#39;l\u0026#39;-\u0026#39;a\u0026#39;] = 1; qwerty[\u0026#39;z\u0026#39;-\u0026#39;a\u0026#39;] = 2; qwerty[\u0026#39;x\u0026#39;-\u0026#39;a\u0026#39;] = 2; qwerty[\u0026#39;c\u0026#39;-\u0026#39;a\u0026#39;] = 2; qwerty[\u0026#39;v\u0026#39;-\u0026#39;a\u0026#39;] = 2; qwerty[\u0026#39;b\u0026#39;-\u0026#39;a\u0026#39;] = 2; qwerty[\u0026#39;n\u0026#39;-\u0026#39;a\u0026#39;] = 2; qwerty[\u0026#39;m\u0026#39;-\u0026#39;a\u0026#39;] = 2; } public String[] findWords(String[] words) { int[] qwerty = new int[26]; mapping(qwerty); List\u0026lt;String\u0026gt; ans = new ArrayList\u0026lt;\u0026gt;(); for (String word: words) { boolean ok = true; for (int i = 0; i \u0026lt; word.length(); i++) { if (qwerty[word.toLowerCase().charAt(i) - \u0026#39;a\u0026#39;] != qwerty[word.toLowerCase().charAt(0) - \u0026#39;a\u0026#39;]) ok = false; } if (ok) ans.add(word); } return ans.toArray(new String[ans.size()]); } } "},{"id":127,"href":"/docs/codes/0500-to-0599/0507.-Perfect-Number/","title":"0507. Perfect Number","section":"0500 to 0599","content":" 0507. Perfect Number # 题目 # 对于一个 正整数,如果它除了和它自身以外的所有 正因子 之和相等,称它为 「完美数」。 给定一个 整数 n,如果是完美数,返回 true;否则返回 false。 思路 # 模拟 # 代码 # 模拟 # class Solution { public boolean checkPerfectNumber (int num) { if (num == 1) return false; int sum = 1; for (int i = 2; i \u0026lt; Math.sqrt((double) num); i++) { if (num % i == 0) { sum += i == num / i ? i : i + num / i; } } return sum == num; } } 致谢 # 宫水三叶\n"},{"id":128,"href":"/docs/codes/0500-to-0599/0513.-Find-Bottom-Left-Tree-Value/","title":"0513. Find Bottom Left Tree Value","section":"0500 to 0599","content":" 0513. Find Bottom Left Tree Value # 题目 # 给定一棵二叉树的 根节点 root,找出该二叉树的 最底层 最左边 节点的值。\n假定二叉树至少有一个节点。\n思路 # 层数遍历 代码 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public int findBottomLeftValue(TreeNode root) { int ans = root.val; Queue\u0026lt;TreeNode\u0026gt; queue = new Linkedlist\u0026lt;\u0026gt;(); queue.offer(root); while (queue.size() != 0) { int layerSize = queue.size(); ans = queue.peek().val; for (int i = 0; i \u0026lt; layerSize; i++) { TreeNode node = queue.poll(); if (node.left != null) queue.offer(node.left); if (node.right != null) queue.offer(node.right); } } return ans; } } "},{"id":129,"href":"/docs/codes/0500-to-0599/0515.-Find-Largest-Value-in-Each-Tree-Row/","title":"0515. Find Largest Value in Each Tree Row","section":"0500 to 0599","content":" 515. Find Largest Value in Each Tree Row # 题目 # 给定一棵二叉树的根节点 root,找出该二叉树中每一层的最大值。\n思路 # 代码 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public List\u0026lt;Integer\u0026gt; largestValues(TreeNode root) { List\u0026lt;Integer\u0026gt; ans = new LinkedList\u0026lt;\u0026gt;(); if (root == null) return ans; Queue\u0026lt;TreeNode\u0026gt; queue = new LinkedList\u0026lt;\u0026gt;(); queue.offer(root); while (queue.size() != 0) { int layerSize = queue.size(), layerMax = queue.peek().val; for (int i = 0; i \u0026lt; layerSize; i++) { TreeNode node = queue.poll(); layerMax = Math.max(layerMax, node.val); if (node.left != null) queue.offer(node.left); if (node.right != null) queue.offer(node.right); } ans.add(layerMax); } return ans; } } "},{"id":130,"href":"/docs/codes/0500-to-0599/0520.-Detect-Capital/","title":"0520. Detect Capital","section":"0500 to 0599","content":" 0520. Detect Capital # 题目 # 定义单词的大写用法的正确使用情景为:\n全部字母都是大写,比如 \u0026quot;USA\u0026quot; 。 单词中所有字母都不是大写,比如 \u0026quot;leetcode\u0026quot; 。 如果单词不只含有一个字母,只有首字母大写, 比如 \u0026quot;Google\u0026quot; 。 给定字符串 word 。如果大写用法正确,返回 true ;否则,返回 false 。\n思路 # 模拟 # 代码 # 模拟 # class Solution { public boolean detectCapitalUse(String word) { int cnt = 0; for (int i = 0; i \u0026lt; word.length(); i++) { if (Character.isUpperCase(word.charAt(i))) cnt++; } return cnt == word.length() || cnt == 0 || (cnt == 1 \u0026amp;\u0026amp; Character.isUpperCase(word.charAt(0))); } } "},{"id":131,"href":"/docs/codes/0500-to-0599/0537.-Complex-Number-Multiplication/","title":"0537. Complex Number Multiplication","section":"0500 to 0599","content":" 0537. Complex Number Multiplication # 题目 # 复数 可以用字符串表示,遵循 \u0026quot;**实部**+**虚部**i\u0026quot; 的形式,并满足下述条件: 实部 是一个整数,取值范围是 [-100, 100] 虚部 也是一个整数,取值范围是 [-100, 100] i2 == -1 给你两个字符串表示的复数 num1 和 num2 ,请你遵循复数表示形式,返回表示它们乘积的字符串。 思路 # 模拟 # 正则 # 代码 # 模拟 # class Solution { /** (a + bj)(c + dj) = (ac - bd) + (ad + bc) j */ public String[] parseComplex(String num) { String real = \u0026#34;\u0026#34;, imag = \u0026#34;\u0026#34;; boolean imagFlag = false; char[] charArray = num.toCharArray(); for (char ch: charArray) { if (ch == \u0026#39;i\u0026#39;) break; if (ch == \u0026#39;+\u0026#39;) imagFlag = true; else if (imagFlag == false) real += String.valueOf(ch); else imag += String.valueOf(ch); } return new String[]{real, imag}; } public String complexNumberMultiply(String num1, String num2) { String[] realImag1 = parseComplex(num1), realImag2 = parseComplex(num2); int real1 = Integer.parseInt(realImag1[0]), imag1 = Integer.parseInt(realImag1[1]); int real2 = Integer.parseInt(realImag2[0]), imag2 = Integer.parseInt(realImag2[1]); return String.valueOf(real1 * real2 - imag1 * imag2) + \u0026#34;+\u0026#34; + String.valueOf(real1 * imag2 + imag1 * real2) + \u0026#34;i\u0026#34;; } } 致谢 # 宫水三叶\n"},{"id":132,"href":"/docs/codes/0500-to-0599/0541.-Reverse-String-ii/","title":"0541. Reverse String Ii","section":"0500 to 0599","content":" 541. Reverse String II # 题目 # 给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。\n如果剩余字符少于 k 个,则将剩余字符全部反转。 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。 思路 # 代码 # class Solution { public void reversePart(char[] charArray, int left, int right) { while (left \u0026lt; right) { char temp = charArray[left]; charArray[left] = charArray[right]; charArray[right] = temp; left += 1; right -= 1; } } public String reverseStr(String s, int k) { char[] charArray = s.toCharArray(); int cycle = charArray.length / (2 * k); for (int i=0; i\u0026lt;cycle; i++) { int left = i * (2 * k), right = left + k - 1; reversePart(charArray, left, right); } int reminder = charArray.length % (2 * k); if (reminder \u0026lt; k) reversePart(charArray, cycle * (2 * k), cycle * (2 * k) + reminder - 1); else reversePart(charArray, cycle * (2 * k), cycle * (2 * k) + k - 1); return String.valueOf(charArray); } } "},{"id":133,"href":"/docs/codes/0500-to-0599/0551.-Student-Attendance-Record-i/","title":"0551. Student Attendance Record I","section":"0500 to 0599","content":" 0551. Student Attendance Record I # 题目 # 给定表示学生出勤记录的字符串 s ,每个字符用于标记当天的出勤情况。\n记录中只含下面三种字符:\n'A':Absent,缺勤 'L':Late,迟到 'P':Present,到场 如果学生能够 同时 满足下面两个条件,则可以获得出勤奖励:\n按 总出勤 计,学生缺勤('A')严格 少于两天。 学生 不会 存在 连续 3 天或 连续 3 天以上的迟到('L')记录。 如果学生可以获得出勤奖励,返回 true ;否则,返回 false 。 思路 # 模拟 # 代码 # 模拟 # class Solution { public boolean checkRecord(String s) { int numAbsent = 0, numLate = 0; for (int i = 0; i \u0026lt; s.length(); i++) { if (s.charAt(i) == \u0026#39;A\u0026#39;) { if (++numAbsent == 2) return false; numLate = 0; } else if (s.charAt(i) == \u0026#39;L\u0026#39;) { if (++numLate == 3) return false; } else numLate = 0; } return true; } } "},{"id":134,"href":"/docs/codes/0500-to-0599/0557.-Reverse-Words-in-a-String-iii/","title":"0557. Reverse Words in a String Iii","section":"0500 to 0599","content":" 0557. Reverse Words in a String iii # 题目 # 给定字符串 s,反转字符串中每个单词的字符顺序,同时保留空格和单词的初始顺序。 思路 # 双指针 # 代码 # 双指针 # class Solution { public String reverseWords(String s) { String[] words = s.split(\u0026#34; \u0026#34;); for (int i = 0; i \u0026lt; words.length; i++) { char[] charArray = words[i].toCharArray(); int left = 0, right = charArray.length - 1; while (left \u0026lt; right) { char temp = charArray[left]; charArray[left] = charArray[right]; charArray[right] = temp; left++; right--; } words[i] = String.valueOf(charArray); } String ans = words[0]; for (int i = 1; i \u0026lt; words.length; i++) ans += \u0026#34; \u0026#34; + words[i]; return ans; } } "},{"id":135,"href":"/docs/codes/0500-to-0599/0559.-Maximum-Depth-of-N-ary-Tree/","title":"0559. Maximum Depth of N Ary Tree","section":"0500 to 0599","content":" 0559. Maximum Depth of N-ary Tree # 题目 # 给定一个 n 叉树,找到其最大深度。\n最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。\n思路 # 层序遍历 代码 # class Node { public int val; public List\u0026lt;Node\u0026gt; children; public Node() {} public Node(int _val) { val = _val; } public Node(int _val, List\u0026lt;Node\u0026gt; _children) { val = _val; children = _children; } } class Solution { public int maxDepth(Node root) { if (root == null) return 0; int depth = 0; Queue\u0026lt;Node\u0026gt; queue = new LinkedList\u0026lt;\u0026gt;(); queue.offer(root); while (queue.size() != 0) { int layerSize = queue.size(); depth += 1; for (int i = 0; i \u0026lt; layerSize; i++) { for (Node child: queue.poll().children) { queue.offer(child); } } } return depth; } } "},{"id":136,"href":"/docs/codes/0500-to-0599/0563.-Binary-Tree-Tilt/","title":"0563. Binary Tree Tilt","section":"0500 to 0599","content":" 0563. Binary Tree Tilt # 题目 # 给定二叉树根节点 root ,计算并返回 整个树 的坡度 。 一个树的 节点的坡度 定义为,该节点左子树的节点之和和右子树节点之和的 差的绝对值 。如果没有左子树的话,左子树的节点之和为 0 ;没有右子树的话也是一样。空结点的坡度是 0 。 整个树 的坡度是其所有节点的坡度之和。 思路 # 递归 # 代码 # 递归 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public int sum(TreeNode root, List\u0026lt;Integer\u0026gt; tilt) { if (root == null) return 0; int leftSum = sum(root.left, tilt); int rightSum = sum(root.right, tilt); tilt.add(Math.abs(leftSum - rightSum)); return leftSum + rightSum + root.val; } public int findTilt(TreeNode root) { List\u0026lt;Integer\u0026gt; tilt = new ArrayList\u0026lt;\u0026gt;(); sum(root, tilt); int ans = 0; for (int val: tilt) ans += val; return ans; } } "},{"id":137,"href":"/docs/codes/0500-to-0599/0566.-Reshape-the-Matrix/","title":"0566. Reshape the Matrix","section":"0500 to 0599","content":" 0566. Reshape the Matrix # 题目 # 在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原始数据。 给你一个由二维数组 mat 表示的 m x n 矩阵,以及两个正整数 r 和 c ,分别表示想要的重构的矩阵的行数和列数。 重构后的矩阵需要将原始矩阵的所有元素以相同的 行遍历顺序 填充。 如果具有给定参数的 reshape 操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。 思路 # 代码 # class Solution { public int[][] matrixReshape(int[][] mat, int r, int c) { int M = mat.length, N = mat[0].length; if (M * N != r * c) return mat; int[][] ans = new int[r][c]; for (int i = 0; i \u0026lt; r; i++) { for (int j = 0; j \u0026lt; c; j++) { int index = i * c + j; int mIndex = index / N, nIndex = index % N; ans[i][j] = mat[mIndex][nIndex]; } } return ans; } } "},{"id":138,"href":"/docs/codes/0500-to-0599/0575.-Distribute-Candies/","title":"0575. Distribute Candies","section":"0500 to 0599","content":" 0575. Distribute Candies # 题目 # Alice 有 n 枚糖,其中第 i 枚糖的类型为 candyType[i] 。Alice 注意到她的体重正在增长,所以前去拜访了一位医生。 医生建议 Alice 要少摄入糖分,只吃掉她所有糖的 n / 2 即可(n 是一个偶数)。Alice 非常喜欢这些糖,她想要在遵循医生建议的情况下,尽可能吃到最多不同种类的糖。 给你一个长度为 n 的整数数组 candyType,返回: Alice 在仅吃掉 n / 2 枚糖的情况下,可以吃到糖的 最多 种类数。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int distributeCandies(int[] candyType) { Set\u0026lt;Integer\u0026gt; set = new HashSet\u0026lt;\u0026gt;(); for(int type: candyType) set.add(type); return Math.min(set.size(), candyType.length / 2); } } "},{"id":139,"href":"/docs/codes/0500-to-0599/0589.-N-ary-Tree-Preorder-Traversal/","title":"0589. N Ary Tree Preorder Traversal","section":"0500 to 0599","content":" 589. N-ary Tree Preorder Traversal # 题目 # 给定一个 n 叉树的根节点 root,返回其节点值的 前序遍历。\n思路 # 递归 迭代 代码 # 递归 # class Node { public int val; public List\u0026lt;Node\u0026gt; children; public Node() {} public Node(int _val) { val = _val; } public Node(int _val, List\u0026lt;Node\u0026gt; _children) { val = _val; children = _children; } } class Solution { public void traversal(Node root, List\u0026lt;Integer\u0026gt; ans) { if (root == null) return; ans.add(root.val); for (Node child: root.children) traversal(child, ans); } public List\u0026lt;Integer\u0026gt; preorder(Node root) { List\u0026lt;Integer\u0026gt; ans = new LinkedList\u0026lt;\u0026gt;(); traversal(root, ans); return ans; } } 迭代 # "},{"id":140,"href":"/docs/codes/0500-to-0599/0590.-N-ary-Tree-Postorder-Traversal/","title":"0590. N Ary Tree Postorder Traversal","section":"0500 to 0599","content":" 590. N-ary Tree Postorder Traversal # 题目 # 给定一个 n 叉树的根节点 root,返回其节点值的 后序遍历。\n思路 # 递归 迭代 代码 # 递归 # class Node { public int val; public List\u0026lt;Node\u0026gt; children; public Node() {} public Node(int _val) { val = _val; } public Node(int _val, List\u0026lt;Node\u0026gt; _children) { val = _val; children = _children; } } class Solution { public void traversal(Node root, List\u0026lt;Integer\u0026gt; ans) { if (root == null) return; for (Node child: root.children) traversal(child, ans); ans.add(root.val); } public List\u0026lt;Integer\u0026gt; postorder(Node root) { List\u0026lt;Integer\u0026gt; ans = new LinkedList\u0026lt;\u0026gt;(); traversal(root, ans); return ans; } } 迭代 # "},{"id":141,"href":"/docs/codes/0500-to-0599/0594.-Longest-Harmonious-Subsequence/","title":"0594. Longest Harmonious Subsequence","section":"0500 to 0599","content":" 0594. Longest Harmonious Subsequence # 题目 # 和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是 1 。 现在,给你一个整数数组 nums ,请你在所有可能的子序列中找到最长的和谐子序列的长度。 数组的子序列是一个由数组派生出来的序列,它可以通过删除一些元素或不删除元素、且不改变其余元素的顺序而得到。 思路 # 模拟 # 滑动窗口 # 代码 # 模拟 # class Solution { public int findLHS(int[] nums) { Map\u0026lt;Integer, Integer\u0026gt; map = new HashMap\u0026lt;\u0026gt;(); for (int num: nums) map.put(num, map.getOrDefault(num, 0) + 1); int ans = 0; for (int num: nums) { if (map.containsKey(num-1)) ans=Math.max(ans, map.get(num-1)+map.get(num)); } return ans; } } 迭代 # 致谢 # 宫水三叶\n"},{"id":142,"href":"/docs/codes/0500-to-0599/0598.-Range-Addition-II/","title":"0598. Range Addition Ii","section":"0500 to 0599","content":" 0598. Range Addition II # 题目 # 给你一个 m x n 的矩阵 M ,初始化时所有的 0 和一个操作数组 op ,其中 ops[i] = [ai, bi] 意味着当所有的 0 \u0026lt;= x \u0026lt; ai 和 0 \u0026lt;= y \u0026lt; bi 时, M[x][y] 应该加 1。 在 执行完所有操作后 ,计算并返回 矩阵中最大整数的个数 。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int maxCount(int m, int n, int[][] ops) { int[] ans = new int[]{m, n}; for (int[] op: ops) { ans[0] = Math.min(ans[0], op[0]); ans[1] = Math.min(ans[1], op[1]); } return ans[0] * ans[1]; } } "},{"id":143,"href":"/docs/codes/0500-to-0599/0599.-Minimum-Index-Sum-of-Two-Lists/","title":"0599. Minimum Index Sum of Two Lists","section":"0500 to 0599","content":" 0599. Minimum Index Sum of Two Lists # 题目 # 假设 Andy 和 Doris 想在晚餐时选择一家餐厅,并且他们都有一个表示最喜爱餐厅的列表,每个餐厅的名字用字符串表示。 你需要帮助他们用最少的索引和找出他们共同喜爱的餐厅。 如果答案不止一个,则输出所有答案并且不考虑顺序。 你可以假设答案总是存在。 思路 # 模拟 # 代码 # 模拟 # class Solution { public String[] findRestaurant(String[] list1, String[] list2) { int indexSum = Integer.MAX_VALUE; List\u0026lt;String\u0026gt; ans = new LinkedList\u0026lt;\u0026gt;(); Map\u0026lt;String, Integer\u0026gt; map = new HashMap\u0026lt;\u0026gt;(); for (int i = 0; i \u0026lt; list1.length; i++) map.put(list1[i], i); for (int i = 0; i \u0026lt; list2.length; i++) { String restaurant = list2[i]; if (map.containsKey(restaurant)) { int sum = i + map.get(restaurant); if (sum == indexSum) ans.add(restaurant); else if (sum \u0026lt; indexSum) { indexSum = sum; ans = new LinkedList\u0026lt;\u0026gt;(); ans.add(restaurant); } } } return ans.toArray(new String[ans.size()]); } } "},{"id":144,"href":"/docs/codes/0600-to-0699/0617.-Merge-Two-Binary-Trees/","title":"0617. Merge Two Binary Trees","section":"0600 to 0699","content":" 617. Merge Two Binary Trees # 题目 # 给定两棵二叉树 root1 和 root2。\n想象一下,当泥浆其中一棵覆盖到另一棵上时,两棵树上的一些节点将会重叠(而另一些不会)。需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。\n返回合并后的二叉树。\n思路 # 代码 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode (int val) { this.val = val; } TreeNode (int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public TreeNode mergeTrees(TreeNode root1, TreeNode root2) { if (root1 == null) return root2; if (root2 == null) return root1; root1.val += root2.val; root1.left = mergeTrees(root1.left, root2.left); root1.right = mergeTrees(root1.right, root2.right); return root; } } "},{"id":145,"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":146,"href":"/docs/codes/0600-to-0699/0637.-Average-of-Levels-in-Binary-Tree/","title":"0637. Average of Levels in Binary Tree","section":"0600 to 0699","content":" 637. Average of Levels in Binary Tree # 题目 # 给定一个非空二叉树的根节点 root,以数组的形式返回每一层节点的平均值。\n与实际答案相差 10^-5 以内的答案可以被接受。\n思路 # 代码 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode (int val) { this.val = val; } TreeNode (int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public List\u0026lt;Double\u0026gt; averageOfLevels(TreeNode root) { List\u0026lt;Double\u0026gt; ans = new LinkedList\u0026lt;\u0026gt;(); if (root == null) return ans; Queue\u0026lt;TreeNode\u0026gt; queue = new LinkedList\u0026lt;\u0026gt;(); queue.offer(root); while (queue.size() != 0) { int layerSize = queue.size(); double sum = 0; for (int i = 0; i \u0026lt; layerSize; i++) { TreeNode node = queue.poll(); if (node.left != null) queue.offer(node.left); if (node.right != null) queue.offer(node.right); sum += node.val; } ans.add(sum / layerSize); } return ans; } } "},{"id":147,"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":148,"href":"/docs/codes/0600-to-0699/0643.-Maximum-Average-Subarray-i/","title":"0643. Maximum Average Subarray I","section":"0600 to 0699","content":" 0643. Maximum Average Subarray i # 题目 # 给你一个由 n 个元素组成的整数数组 nums 和一个整数 k 。 请你找出平均数最大且 长度为 k 的连续子数组,并输出该最大平均数。 任何误差小于 10^-5 的答案都将被视为正确答案。 思路 # 模拟 # 代码 # 模拟 # class Solution { public double findMaxAverage(int[] nums, int k) { int ans = 0, windowSum = 0; for (int i = 0; i \u0026lt; k; i++) windowSum += nums[i]; ans = windowSum; int left = 0, right = k - 1; while (right \u0026lt;= nums.length - 2) { windowSum += nums[++right] - nums[left++]; ans = Math.max(ans, windowSum); } return (double) ans / k; } } "},{"id":149,"href":"/docs/codes/0600-to-0699/0645.-Set-Mismatch/","title":"0645. Set Mismatch","section":"0600 to 0699","content":" 645. Set Mismatch # 题目 # 集合 s 包含从 1 到 n 的整数。但集合 丢失了一个数字 并 有一个数字重复。\n给定数组 nums 代表集合 s 发生错误后的结果。\n先找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。\n思路 # 代码 # class Solution { public int[] findErrorNums(int[] nums) { int[] ans = new int[2]; /** 另 1~n 与 nums 进行异或操作,返回值为 missing ^ duplicate */ int xor = 0; int[] appearance = new int[nums.length]; for (int i = 0; i \u0026lt; nums.length; i++) { xor ^= (i + 1) ^ nums[i]; appearance[nums[i] - 1] += 1; if (appearance[nums[i] - 1] == 2) ans[0] = nums[i]; } /** missing = missing ^ duplicate ^ duplicate */ ans[1] = xor ^ ans[0]; return ans; } } "},{"id":150,"href":"/docs/codes/0600-to-0699/0657.-Robot-Return-to-Origin/","title":"0657. Robot Return to Origin","section":"0600 to 0699","content":" 0657. Robot Return to Origin # 题目 # 在二维平面上,有一个机器人从原点 (0, 0) 开始。给出它的移动顺序,判断这个机器人在完成移动后是否在 (0, 0) 处结束。 移动顺序由字符串 moves 表示。字符 move[i] 表示其第 i 次移动。机器人的有效动作有 R(右),L(左),U(上)和 D(下)。 如果机器人在完成所有动作后返回原点,则返回 true。否则,返回 false。 注意:机器人“面朝”的方向无关紧要。 “R” 将始终使机器人向右移动一次,“L” 将始终向左移动等。此外,假设每次移动机器人的移动幅度相同。 思路 # 模拟 # 代码 # 模拟 # class Solution { public boolean judgeCircle(String moves) { if (moves.length() % 2 == 1) return false; int L = 0, R = 0, U = 0, D = 0; for (int i = 0; i \u0026lt; moves.length(); i++) { switch (moves.charAt(i)) { case \u0026#39;L\u0026#39; : L += 1; break; case \u0026#39;R\u0026#39; : R += 1; break; case \u0026#39;U\u0026#39; : U += 1; break; case \u0026#39;D\u0026#39; : D += 1; break; } } return L == R \u0026amp;\u0026amp; U == D; } } "},{"id":151,"href":"/docs/codes/0600-to-0699/0661.-Image-Smoother/","title":"0661. Image Smoother","section":"0600 to 0699","content":" 0661. Image Smoother # 题目 # 图像平滑器 是大小为 3 x 3 的过滤器,用于对图像的每个单元格平滑处理,平滑处理后单元格的值为该单元格的平均灰度。 每个单元格的 平均灰度 定义为:该单元格自身及其周围的 8 个单元格的平均值,结果需向下取整。(即,需要计算蓝色平滑器中 9 个单元格的平均值)。 如果一个单元格周围存在单元格缺失的情况,则计算平均灰度时不考虑缺失的单元格(即,需要计算红色平滑器中 4 个单元格的平均值)。 思路 # 模拟 # 前缀和 # 代码 # 模拟 # class Solution { public int conv(int i, int j, int[][] img) { int M = img.length, N = img[0].length; int numerator = 0, denominator = 0; for (int row = i-1; row \u0026lt;= i+1; row++) { for (int col = j-1; col \u0026lt;= j+1; col++) { if (0 \u0026lt;= row \u0026amp;\u0026amp; row \u0026lt; M \u0026amp;\u0026amp; 0 \u0026lt;= col \u0026amp;\u0026amp; col \u0026lt; N) { numerator += img[row][col]; denominator++; } } } return numerator / denominator; } public int[][] imageSmoother(int[][] img) { int M = img.length, N = img[0].length; int[][] ans = new int[M][N]; for (int i = 0; i \u0026lt; M; i++) { for (int j = 0; j \u0026lt; N; j++) { ans[i][j] = conv(i, j, img); } } return ans; } } 前缀和 # 致谢 # 宫水三叶\n"},{"id":152,"href":"/docs/codes/0600-to-0699/0682.-Baseball-Game/","title":"0682. Baseball Game","section":"0600 to 0699","content":" 682. Baseball Game # 题目 # 你现在是一场采用特殊赛制棒球比赛的记录员。这场比赛由若干回合组成,过去几回合的得分可能会影响以后几回合的得分。\n比赛开始时,记录是空白的。你会得到一个记录操作的字符串列表 ops,其中 ops[i] 是你需要记录的第 i 项操作,ops 遵循下述规则:\n整数 x - 表示本回合新获得分数 x \u0026quot;+\u0026quot; - 表示本回合新获得的得分是前两次得分的总和。题目数据保证记录此操作时前面总是存在两个有效的分数。 \u0026quot;D\u0026quot; - 表示本回合新获得的得分是前一次得分的两倍。题目数据保证记录此操作时前面总是存在一个有效的分数。 \u0026quot;C\u0026quot; - 表示前一次得分无效,将其从记录中移除。题目数据保证记录此操作时前面总是存在一个有效的分数。 返回记录中所有得分的总和。\n思路 # 栈 代码 # class Solution { public int calPoints(String[] operations) { Stack\u0026lt;Integer\u0026gt; score = new Stack\u0026lt;\u0026gt;(); for (String operation: operations) { if (operation.equals(\u0026#34;+\u0026#34;) == true) { int temp = score.pop(), newVal = temp + score.peek(); score.push(temp); score.push(newVal); } else if (operation.equals(\u0026#34;D\u0026#34;) == true) score.push(2 * score.peek()); else if (operation.equals(\u0026#34;C\u0026#34;) == true) score.pop(); else score.push(Integer.parseInt(operation)); } int ans = 0; for (int s: score) ans += s; return ans; } } "},{"id":153,"href":"/docs/codes/0600-to-0699/0693.-Binary-Number-with-Alternating-Bits/","title":"0693. Binary Number With Alternating Bits","section":"0600 to 0699","content":" 693. Binary Number with Alternating Bits # 题目 # 给定一个正整数,检查其二进制表示是否总是 0、1 交替出现。换言之,二进制表示中相邻两位的数字永不相同。\n思路 # 代码 # class Solution { public boolean hasAlternatingBits(int n) { /** 先定位最高位的 1 */ int start = 0; for (int i = 30; i \u0026gt;= 0; i--) { if (((n \u0026gt;\u0026gt; i) \u0026amp; 1) == 0) continue; start = i; break; } /** 判断数 n 的二进制表示中相邻两位的数字永不相同 */ for (int i = start - 1, lastBit = ((n \u0026gt;\u0026gt; start) \u0026amp; 1); i \u0026gt;= 0; i--) { if (((n \u0026gt;\u0026gt; i) \u0026amp; 1) == lastBit) return false; lastBit = lastBit = 1 ? 0 : 1; } return true; } } "},{"id":154,"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":155,"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":156,"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":157,"href":"/docs/codes/0700-to-0799/0709.-To-Lower-Case/","title":"0709. to Lower Case","section":"0700 to 0799","content":" 0709. To Lower Case # 题目 # 给定字符串 s,将该字符串中的大写字母转成相同的小写字母,返回新的字符串。 思路 # 模拟 # 代码 # 模拟 # class Solution { public String toLowerCase(String s) { char[] charArray = s.toCharArray(); for (int i = 0; i \u0026lt; charArray.length; i++) { if (Character.isLetter(charArray[i]) \u0026amp;\u0026amp; charArray[i] \u0026lt; \u0026#39;a\u0026#39;) charArray[i] |= 1 \u0026lt;\u0026lt; 5; } return Stirng.valueOf(charArray); } } 致谢 # 疯子\n"},{"id":158,"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":159,"href":"/docs/codes/0700-to-0799/0724.-Find-Pivot-Index/","title":"0724. Find Pivot Index","section":"0700 to 0799","content":" 0724. Find Pivot Index # 题目 # 给定整数数组 nums ,计算数组的 中心下标 。 数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。 如果中心下标位于数组最左端,那么左侧数之和视为 0 ,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。 如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回 -1 。 思路 # 前缀和 # 代码 # 前缀和 # class Solution { public int pivotIndex(int[] nums) { int total = 0; for (int num: nums) total += num; int prefix = 0; for (int i = 0; i \u0026lt; nums.length; i++) { if (prefix == total - prefix - nums[i]) return i; prefix += nums[i]; } return -1; } } "},{"id":160,"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":161,"href":"/docs/codes/0700-to-0799/0735.-Asteroid-Collision/","title":"0735. Asteroid Collision","section":"0700 to 0799","content":" 0735. Asteroid Collision # 题目 # 给定一个整数数组 asteroids,表示在同一行的行星。\n对于数组中的每一个元素,其绝对值表示行星的大小,正负表示行星的移动方向(正表示向右移动,负表示向左移动)。每一颗行星以相同的速度移动。\n找出碰撞后剩下的所有行星。碰撞规则:两个行星相互碰撞,较小的行星会爆炸。如果两颗行星大小相同,则两颗行星都会爆炸。两颗移动方向相同的行星,永远不会发生碰撞。\n思路 # 栈 # 代码 # 栈 # class Solution { public int[] asteroidCollision(int[] asteroids) { Stack\u0026lt;Integer\u0026gt; stack = new Stack\u0026lt;\u0026gt;(); for (int asteroid: asteroids) { boolean isExist = true; if (stack.size() == 0) stack.push(asteroid); else if (stack.peek() * asteroid \u0026gt; 0) stack.push(asteroid); else if (stack.peek() \u0026lt; 0 \u0026amp;\u0026amp; asteroid \u0026gt; 0) stack.push(asteroid); else while (isExist == true) { if (stack.size() == 0 || stack.peek() \u0026lt; 0) { stack.push(asteroid); break; } else if (stack.peek() + asteroid == 0) { stack.pop(); isExist = false; } else if (stack.peek() + asteroid \u0026gt; 0) isExist = false; else stack.pop(); } } int[] ans = new int[stack.size()]; for (int i = 0; i \u0026lt; ans.length; i++) ans[ans.length-1-i] = stack.pop(); return ans; } } "},{"id":162,"href":"/docs/codes/0700-to-0799/0744.-Find-Smallest-Letter-Greater-Than-Target/","title":"0744. Find Smallest Letter Greater Than Target","section":"0700 to 0799","content":" 0744. Find Smallest Letter Greater Than Target # 题目 # 给定按非递减顺序排序的字符数组 letters 以及一个字符 target。letters 里至少有两个不同的字符。\n返回 letters 中大于 target 的最小的字符。如果不存在这样的字符,则返回 letters 的第一个字符。\n思路 # 二分 # 代码 # 二分 # class Solution { public char nextGreatestLetter(char[] letters, char target) { int left = 0, right = letters.length; while (left \u0026lt; right) { int mid = left + (right - left) / 2; if (letters[mid] \u0026gt; target) right = mid; else left = mid + 1; } return right == letters.length ? letters[0] : letters[right]; } } "},{"id":163,"href":"/docs/codes/0700-to-0799/0746.-Min-Cost-Climbing-Stairs/","title":"0746. Min Cost Climbing Stairs","section":"0700 to 0799","content":" 0746. Min Cost Climbing Stairs # 题目 # 给定整数数组 cost,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦支付此费用,即可选择向上爬一个或两个台阶。\n可以选择从下标为 0 或 下标为 1 的台阶开始爬楼梯。\n计算并返回到达楼梯顶部的最低花费。\n思路 # 动态规划 # 定义状态 costs[i] 为由下标为 i 的台阶到达楼梯顶的最小花费。 代码 # 动态规划 # class Solution { public int minCostClimbingStairs(int[] cost) { int nStairs = cost.length; int[] costs = new int[nStairs]; costs[nStairs - 1] = cost[nStairs - 1]; costs[nStairs - 2] = cost[nStairs - 2]; for (int i = nStairs - 3; i \u0026gt; -1; i--) { costs[i] = cost[i] + Math.min(costs[i + 1], costs[i + 2]); } return Math.min(costs[0], costs[1]); } } "},{"id":164,"href":"/docs/codes/0700-to-0799/0747.-Largest-Number-At-Least-Twice-of-Others/","title":"0747. Largest Number at Least Twice of Others","section":"0700 to 0799","content":" 747. Largest Number At Least Twice of Others # 题目 # 给定整数数组 nums ,其中存在 唯一的 最大整数 。\n找出数组中的最大元素并检查它是否 至少是数组中每个其他数字的两倍 。如果是,则返回 最大元素的下标 ,否则返回 -1 。\n思路 # 双指针 # 代码 # 双指针 # class Solution { public int dominantIndex(int[] nums) { if (nums.length == 1) return 0; /** 双指针 */ int first = -1, second = -1; if (nums[0] \u0026gt;= nums[1]) { first = 0; second = 1; } else { first = 1; second = 0; } /** 遍历 */ for (int i = 2; i \u0026lt; nums.length; i++) { if (nums[i] \u0026gt;= nums[first]) { second = first; first = i; } else if (nums[i] \u0026gt; nums[second]) second = i; } return nums[first] \u0026gt;= 2 * nums[second] ? first : second; } } "},{"id":165,"href":"/docs/codes/0700-to-0799/0762.-Prime-Number-of-Set-Bits-in-Binary-Representation/","title":"0762. Prime Number of Set Bits in Binary Representation","section":"0700 to 0799","content":" 762. Prime Number of Set Bits in Binary Representation # 题目 # 给定两个整数 left 和 right,在闭区间 [left, right] 范围内,统计并返回 计算置位位数为质数 的整数个数。\n计算置位位数 就是二进制表示中 1 的个数。\n思路 # 代码 # class Solution { public boolean isPrime(int num) { if (num == 1) return false; for (int i = 2; i \u0026lt;= Math.sqrt(num); i++) { if (num % i == 0) return false; } return true; } public int count(int num) { int count = 0; for (int i = 30; i \u0026gt;= 0; i--) { if (((num \u0026gt;\u0026gt; i) \u0026amp; 1) == 1) count += 1; } return count; } public int countPrimeSetBits(int left, int right) { int numPrime = 0; for (int i = left; i \u0026lt;= right; i++) { int num = count(i); if (isPrime(num) == true) numPrime += 1; } return numPrime; } } "},{"id":166,"href":"/docs/codes/0700-to-0799/0771.-Jewels-and-Stones/","title":"0771. Jewels and Stones","section":"0700 to 0799","content":" 0771. Jewels and Stones # 题目 # 给定字符串 jewels 代表石头中宝石的类型,另有一个字符串 stones 代表你拥有的石头。 stones 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。 字母区分大小写,因此 \u0026quot;a\u0026quot; 和 \u0026quot;A\u0026quot; 是不同类型的石头。 思路 # 哈希 # 代码 # 哈希 # class Solution { public int numJewelsInStones(String jewels, String stones) { Set\u0026lt;Character\u0026gt; set = new HashSet\u0026lt;\u0026gt;(); for (int i = 0; i \u0026lt; jewels.length(); i++) set.add(jewels.charAt(i)); int ans = 0; for (int i = 0; i \u0026lt; stones.length(); i++) if (set.contains(stones.charAt(i))) ans++; return ans; } } "},{"id":167,"href":"/docs/codes/0700-to-0799/0796.-Rotate-String/","title":"0796. Rotate String","section":"0700 to 0799","content":" 0796. Rotate String # 题目 # 给定两个字符串, s 和 goal。如果在若干次旋转操作之后,s 能变成 goal ,那么返回 true 。\ns 的 旋转操作 就是将 s 最左边的字符移动到最右边。\n例如, 若 s = 'abcde',在旋转一次之后结果就是'bcdea' 。 思路 # 模拟 # 代码 # 模拟 # class Solution { public String rotate(String s) { String ans = \u0026#34;\u0026#34;; for (int i = 1; i \u0026lt; s.length(); i++) ans += String.valueOf(s.charAt(i)); ans += String.valueOf(s.charAt(0)); return ans; } public boolean rotateString(String s, String goal) { if (s.length() != goal.length()) return false; if (s.equals(goal)) return true; for (int i = 1; i \u0026lt; s.length(); i++) { s = rotate(s); if (s.equals(goal)) return true; } return false; } } 致谢 # 宫水三叶\n"},{"id":168,"href":"/docs/codes/0800-to-0899/0804.-Unique-Morse-Code-Words/","title":"0804. Unique Morse Code Words","section":"0800 to 0899","content":" 0804. Unique Morse Code Words # 题目 # 国际摩尔斯密码定义一种标准编码方式,将每个字母对应于一个由一系列点和短线组成的字符串, 比如:\n'a' 对应 \u0026quot;.-\u0026quot; , 'b' 对应 \u0026quot;-...\u0026quot; , 'c' 对应 \u0026quot;-.-.\u0026quot; ,以此类推。 为了方便,所有 26 个英文字母的摩尔斯密码表如下:\n[\u0026#34;.-\u0026#34;,\u0026#34;-...\u0026#34;,\u0026#34;-.-.\u0026#34;,\u0026#34;-..\u0026#34;,\u0026#34;.\u0026#34;,\u0026#34;..-.\u0026#34;,\u0026#34;--.\u0026#34;,\u0026#34;....\u0026#34;,\u0026#34;..\u0026#34;,\u0026#34;.---\u0026#34;,\u0026#34;-.-\u0026#34;,\u0026#34;.-..\u0026#34;,\u0026#34;--\u0026#34;,\u0026#34;-.\u0026#34;,\u0026#34;---\u0026#34;,\u0026#34;.--.\u0026#34;,\u0026#34;--.-\u0026#34;,\u0026#34;.-.\u0026#34;,\u0026#34;...\u0026#34;,\u0026#34;-\u0026#34;,\u0026#34;..-\u0026#34;,\u0026#34;...-\u0026#34;,\u0026#34;.--\u0026#34;,\u0026#34;-..-\u0026#34;,\u0026#34;-.--\u0026#34;,\u0026#34;--..\u0026#34;] 给你一个字符串数组 words ,每个单词可以写成每个字母对应摩尔斯密码的组合。\n例如,\u0026quot;cab\u0026quot; 可以写成 \u0026quot;-.-..--...\u0026quot; ,(即 \u0026quot;-.-.\u0026quot; + \u0026quot;.-\u0026quot; + \u0026quot;-...\u0026quot; 字符串的结合)。我们将这样一个连接过程称作 单词翻译 。 对 words 中所有单词进行单词翻译,返回不同 单词翻译 的数量。\n思路 # 哈希 # 代码 # 哈希 # class Solution { public String charToString(Character ch) { switch (ch) { case \u0026#39;a\u0026#39; : return \u0026#34;.-\u0026#34;; case \u0026#39;b\u0026#39; : return \u0026#34;-...\u0026#34;; case \u0026#39;c\u0026#39; : return \u0026#34;-.-.\u0026#34;; case \u0026#39;d\u0026#39; : return \u0026#34;-..\u0026#34;; case \u0026#39;e\u0026#39; : return \u0026#34;.\u0026#34;; case \u0026#39;f\u0026#39; : return \u0026#34;..-.\u0026#34;; case \u0026#39;g\u0026#39; : return \u0026#34;--.\u0026#34;; case \u0026#39;h\u0026#39; : return \u0026#34;....\u0026#34;; case \u0026#39;i\u0026#39; : return \u0026#34;..\u0026#34;; case \u0026#39;j\u0026#39; : return \u0026#34;.---\u0026#34;; case \u0026#39;k\u0026#39; : return \u0026#34;-.-\u0026#34;; case \u0026#39;l\u0026#39; : return \u0026#34;.-..\u0026#34;; case \u0026#39;m\u0026#39; : return \u0026#34;--\u0026#34;; case \u0026#39;n\u0026#39; : return \u0026#34;-.\u0026#34;; case \u0026#39;o\u0026#39; : return \u0026#34;---\u0026#34;; case \u0026#39;p\u0026#39; : return \u0026#34;.--.\u0026#34;; case \u0026#39;q\u0026#39; : return \u0026#34;--.-\u0026#34;; case \u0026#39;r\u0026#39; : return \u0026#34;.-.\u0026#34;; case \u0026#39;s\u0026#39; : return \u0026#34;...\u0026#34;; case \u0026#39;t\u0026#39; : return \u0026#34;-\u0026#34;; case \u0026#39;u\u0026#39; : return \u0026#34;..-\u0026#34;; case \u0026#39;v\u0026#39; : return \u0026#34;...-\u0026#34;; case \u0026#39;w\u0026#39; : return \u0026#34;.--\u0026#34;; case \u0026#39;x\u0026#39; : return \u0026#34;-..-\u0026#34;; case \u0026#39;y\u0026#39; : return \u0026#34;-.--\u0026#34;; case \u0026#39;z\u0026#39; : return \u0026#34;--..\u0026#34;; } return \u0026#34;\u0026#34;; } public int uniqueMorseRepresentations(String[] words) { Set\u0026lt;String\u0026gt; set = new HashSet\u0026lt;\u0026gt;(); for (String word: words) { String str = \u0026#34;\u0026#34;; for (int i = 0; i \u0026lt; word.length(); i++) str += charToString(word.charAt(i)); set.add(str); } return set.size(); } } 致谢 # 宫水三叶\n"},{"id":169,"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":170,"href":"/docs/codes/0800-to-0899/0819.-Most-Common-Word/","title":"0819. Most Common Word","section":"0800 to 0899","content":" 0819. Most Common Word # 题目 # 给定一个段落 (paragraph) 和一个禁用单词列表 (banned)。返回出现次数最多,同时不再禁用列表中的单词。 题目保证至少有一个词不在禁用列表中,且答案唯一。 禁用列表中的单词用小写字母表示,不含标点符号。段落中的单词不区分大小写。答案都是小写字母。 paragraph 只包含字母、空格和下列标点符号!?',;. 单词里只包含字母,不会出现省略号或者其他标点符号。 不存在没有连字符或者带有连字符的单词。 思路 # 哈希 # 代码 # 哈希 # class Solution { public String mostCommonWord (String paragraph, String[] banned) { Set\u0026lt;String\u0026gt; set = new HashSet\u0026lt;\u0026gt;(); for (String ban: banned) set.add(ban); Map\u0026lt;String, Integer\u0026gt; map = new HashMap\u0026lt;\u0026gt;(); int maxCnt = 0; String maxWord = \u0026#34;\u0026#34;; Character[] punctuations = new Character[]{\u0026#39;!\u0026#39;, \u0026#39;?\u0026#39;, \u0026#39;\\\u0026#39;\u0026#39;, \u0026#39;,\u0026#39;, \u0026#39;;\u0026#39;, \u0026#39;.\u0026#39;}; for (Character punctuation: punctuations) paragraph = paragraph.replace(puctuation, \u0026#39; \u0026#39;); String[] words = paragraph.split(\u0026#34; \u0026#34;); for (int i = 0; i \u0026lt; words.length; i++) { String word = words[i].toLowerCase(); if (word != \u0026#34;\u0026#34; \u0026amp;\u0026amp; set.contains(word) == false) { map.put(word, map.getOrDefault(word, 0) + 1); if (map.get(word) \u0026gt; maxCnt) { maxCnt = map.get(word); maxWord = word; } } } return maxWord; } } 致谢 # 宫水三叶\n"},{"id":171,"href":"/docs/codes/0800-to-0899/0821.-Shortest-Distance-to-a-Character/","title":"0821. Shortest Distance to a Character","section":"0800 to 0899","content":" 0821. Shortest Distance to a Character # 题目 # 给定字符串 s 和一个字符 c,且 c 是 s 中出现过的字符。 返回整数数组 answer,其中 answer.length == s.length 且 answer[i] 是 s 中从下标 i 到离他 最近 的字符 c 的距离。 两个下标 i 和 j 之间的 距离 为 abs(i - j),其中 abs 是绝对值函数。 思路 # 双向遍历 # BFS # 代码 # 双向遍历 # class Solution { public int[] shortestToChar(String s, char c) { /** 双向扫描数组 */ int[] ans = new int[s.length()]; for (int i = 0; i \u0026lt; ans.length; i++) ans[i] = Integer.MAX_VALUE; int ptr = -1; /** 从后向前扫描数组 */ for (int i = s.length() - 1; i \u0026gt;= 0; i--) { if (s.charAt(i) == c) ptr = i; if (ptr \u0026gt;= i) ans[i] = ptr -i; } /** 从前向后扫描数组 */ for (int i = 0; i \u0026lt; s.length(); i++) { if (s.charAt(i) == c) ptr = i; if (ptr \u0026lt;= i) ans[i] = Math.min(ans[i], i - ptr); } return ans; } } BFS # "},{"id":172,"href":"/docs/codes/0800-to-0899/0824.-Goat-Latin/","title":"0824. Goat Latin","section":"0800 to 0899","content":" 0824. Goat Latin # 题目 # 给你一个由若干单词组成的句子 sentence ,单词间由空格分隔。每个单词仅由大写和小写英文字母组成。 请你将句子转换为 “山羊拉丁文(Goat Latin)”(一种类似于 猪拉丁文 - Pig Latin 的虚构语言)。山羊拉丁文的规则如下: 如果单词以元音开头,在单词后添加\u0026quot;ma\u0026quot; 例如,单词 \u0026quot;apple\u0026quot; 变为 \u0026quot;applema\u0026quot; 。 如果单词以辅音字母开头(即,非元音字母),移除第一个字符并将它放到末尾,之后再添加\u0026quot;ma\u0026quot; 例如,单词 \u0026quot;goat\u0026quot; 变为 \u0026quot;oatgma\u0026quot; 。 根据单词在句子中的索引,在单词最后添加与索引相同数量的字母a,索引从1开始。 例如,在第一个单词后添加 \u0026quot;a\u0026quot; ,在第二个单词后添加 \u0026quot;aa\u0026quot; ,以此类推。 返回将 sentence 转换为山羊拉丁文后的句子。 思路 # 模拟 # 代码 # 模拟 # class Solution { public boolean isVowel(Character ch) { switch (Character.toLowerCase(ch)) { case \u0026#39;a\u0026#39;: case \u0026#39;e\u0026#39;: case \u0026#39;i\u0026#39;: case \u0026#39;o\u0026#39;: case \u0026#39;u\u0026#39;: return true; default: return false; } } public String toGoatLatin(String sentence) { String[] words = sentence.split(\u0026#34; \u0026#34;); for (int i = 0; i \u0026lt;words.length; i++) { Character ch = words[i].charAt(0); words[i] = isVowel(ch) ? words[i] + \u0026#34;ma\u0026#34; : words[i].substring(1) + ch + \u0026#34;ma\u0026#34;; words[i] += \u0026#34;a\u0026#34;.repeat(i+1); } return String.join(\u0026#34; \u0026#34;, words); } } ## 致谢 # 宫水三叶\n"},{"id":173,"href":"/docs/codes/0800-to-0899/0832.-Flipping-an-Image/","title":"0832. Flipping an Image","section":"0800 to 0899","content":" 0832. Flipping an Image # 题目 # 给定一个 n x n 的二进制矩阵 image ,先 水平 翻转图像,然后 反转 图像并返回 结果 。\n水平翻转图片就是将图片的每一行都进行翻转,即逆序。\n例如,水平翻转 [1,1,0] 的结果是 [0,1,1]。 反转图片的意思是图片中的 0 全部被 1 替换, 1 全部被 0 替换。\n例如,反转 [0,1,1] 的结果是 [1,0,0]。\n思路 # 代码 # class Solution { public void swap(int[][] image, int r1, int c1, int r2, int c2) { /** 对于数组元素来讲,这里的最终结果都是0*/ image[r1][c1] ^= image[r2][c2]; image[r2][c2] ^= image[r1][c1]; image[r1][c1] ^= image[r2][c2]; } public int[][] flipAndInvertImage(int[][] image) { int M = image.length, N = image[0].length; /** flip horizontally */ for (int m = 0; m \u0026lt; M; m++) { int n1 = 0, n2 = N - 1; while (n1 \u0026lt; n2) { swap(image, m, n1, m, n2); n1 += 1; n2 -= 1; } } /** invert */ for (int m = 0; m \u0026lt; M; m++) { for (int n = 0; n \u0026lt; N; n++) { image[m][n] = 1 - image[m][n]; } } return image; } } "},{"id":174,"href":"/docs/codes/0800-to-0899/0844.-Backspace-String-Compare/","title":"0844. Backspace String Compare","section":"0800 to 0899","content":" 0844. Backspace String Compare # 题目 # 给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true。# 代表退格字符。 对空文本输入退格字符,文本继续为空。 思路 # 模拟 # 代码 # 模拟 # class Solution { public boolean backspaceCompare(String s, String t) { int ptrS = s.length() - 1, ptrT = t.length() - 1; int cntS = 0, cntT = 0; while (ptrS \u0026gt;= 0 \u0026amp;\u0026amp; ptrT \u0026gt;= 0) { while (ptrS \u0026gt;= 0) { if (s.charAt(ptrS) == \u0026#39;#\u0026#39;) { cntS++; ptrS--; } else if (cntS \u0026gt; 0) { cntS--; ptrS--; } else break; } while (ptrT \u0026gt;= 0) { if (t.charAt(ptrT) == \u0026#39;#\u0026#39;) { cntT+=; ptrT--; } else if (cntT \u0026gt; 0) { cntT--; ptrT--; } else break; } if (ptrS \u0026gt; -1 \u0026amp;\u0026amp; ptrT \u0026gt; -1) { if (s.charAt(ptrS) != t.charAt(ptrT)) return false; ptrS--; ptrT--; } } if (ptrS == -1 \u0026amp;\u0026amp; ptrT != -1) { while (ptrT \u0026gt; -1) { if (t.charAt(ptrT) == \u0026#39;#\u0026#39;) { cntT++; ptrT--; } else if (cntT \u0026gt; 0) { cntT--; ptrT--; } else return false; } } else if (ptrS != -1 \u0026amp;\u0026amp; ptrT == -1) { while (ptrS \u0026gt; -1) { if (s.charAT(ptrS) == \u0026#39;#\u0026#39;) { cntS++; ptrS--; } else if (cntS \u0026gt; 0) { cntS--; ptrS--; } else return false; } } return true; } } "},{"id":175,"href":"/docs/codes/0800-to-0899/0859.-Buddy-Strings/","title":"0859. Buddy Strings","section":"0800 to 0899","content":" 0859. Buddy Strings # 题目 # 给定两个字符串 s 和 goal,若可以通过交换 s 中的两个字母后得到与 goal 相同的结果,则认为 s 与 goal 是亲密字符串。 判断给定的两个字符串是否是亲密字符串。 思路 # 模拟 # 代码 # 模拟 # class Solution { public boolean buddyStrings(String s, String goal) { if (s.length() != goal.length()) return false; Stack\u0026lt;Integer\u0026gt; stack = new Stack\u0026lt;\u0026gt;(); for (int i = 0; i \u0026lt; s.length; i++) { if (s.charAt(i) != goal.charAt(i)) stack.push(i); } if (stack.size() == 0) { int[] count = new int[26]; for (int i = 0; i \u0026lt; s.length(); i++) count[s.charAt(i)-\u0026#39;a\u0026#39;] += 1; for (int cnt: count) if (count \u0026gt; 1) return true; return false; } if (stack.size() != 2) return false; int pos_1 = stack.pop(), pos_2 = stack.pop(); return s.charAt(pos_1) == goal.charAt(pos_2) \u0026amp;\u0026amp; s.charAt(pos_2) == goal.charAt(pos_1); } } "},{"id":176,"href":"/docs/codes/0800-to-0899/0860.-Lemonade-Change/","title":"0860. Lemonade Change","section":"0800 to 0899","content":" 0860. Lemonade Change # 题目 # 在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,一次购买一杯。 每位顾客支付 5 美元、10美元或20美元。必须为每名顾客正确找零,即净交易额为每名顾客支付5美元。 一开始手头没有任何零钱。 给定整数数组bills,其中bills[i]是第i位顾客付的账。 如果能给每位顾客正确找零,返回true,否则返回false。 思路 # 贪心 # 代码 # 贪心 # class Solution { public boolean lemonadeChange(int[] bills) { int five = 0, ten = 0; for (int bill: bills) { if (bill == 5) five++; else if (bill == 10) { if (--five \u0026lt; 0) return false; ten++; } else { if (ten \u0026gt; 0) { ten--; if (--five \u0026lt; 0) return false; } else { five -= 3; if (five \u0026lt; 0) return false; } } } return true; } } 致谢 # "},{"id":177,"href":"/docs/codes/0800-to-0899/0867.-Transpose-Matrix/","title":"0867. Transpose Matrix","section":"0800 to 0899","content":" 0867. Transpose Matrix # 题目 # 给定一个二维整数数组 matrix,返回 matrix 的 转置矩阵。\n矩阵的 转置 是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引。\n思路 # 代码 # class Solution { public int[][] transpose(int[][] matrix) { int m = matrix.length, n = matrix[0].length; int[][] ans = new int[n][m]; for (int i = 0; i \u0026lt; n; i++) { for (int j = 0; j \u0026lt; m; j++) { ans[i][j] = matrix[j][i]; } } return ans; } } "},{"id":178,"href":"/docs/codes/0800-to-0899/0868.-Binary-Gap/","title":"0868. Binary Gap","section":"0800 to 0899","content":" 0868. Binay Gap # 题目 # 给定正整数 n,找到并返回 n 的二进制表示中两个相邻 1 之间的最长距离。若不存在两个相邻的 1,返回 0。\n若只有 0 将两个 1 分隔开,则认为这两个 1 彼此相邻。两个 1 之间的距离是它们的二进制表示中位置的绝对差。\n思路 # 代码 # class Solution { public int binaryGap(int n) { int gap = 0, flag = -1; for (int i = 31; i \u0026gt;= 0; i--) { if (((n \u0026gt;\u0026gt; i) \u0026amp; 1) == 1) { if (flag \u0026gt; 0) gap = Math.max(gap, flag - i); flag = i; } } return gap; } } "},{"id":179,"href":"/docs/codes/0800-to-0899/0876.-Middle-of-the-Linked-List/","title":"0876. Middle of the Linked List","section":"0800 to 0899","content":" 0876. 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":180,"href":"/docs/codes/0800-to-0899/0884.-Uncommon-Words-from-Two-Sentences/","title":"0884. Uncommon Words From Two Sentences","section":"0800 to 0899","content":" 0884. Uncommon Words from Two Sentences # 题目 # 句子 是一串由空格分隔的单词。每个 单词 仅由小写字母组成。 如果某个单词在其中一个句子中恰好出现一次,在另一个句子中却 没有出现 ,那么这个单词就是 不常见的 。 给你两个 句子 s1 和 s2 ,返回所有 不常用单词 的列表。返回列表中单词可以按 任意顺序 组织。 思路 # 哈希 # 代码 # 哈希 # class Solution { public String[] uncommonFromSentences(String s1, String s2) { String[] s1Array = s1.split(\u0026#34; \u0026#34;), s2Array = s2.split(\u0026#34; \u0026#34;); Map\u0026lt;String, Integer\u0026gt; s1Map = new HashMap\u0026lt;\u0026gt;(), s2Map = new HashMap\u0026lt;\u0026gt;(); for (String str: s1Array) s1Map.put(str, s1Map.getOrDefault(str, 0) + 1); for (String str: s2Array) s2Map.put(str, s2Map.getOrDefault(str, 0) + 1); int sz = 0; for (String key: s1Map.keySet()) if (s1Map.get(key) == 1 \u0026amp;\u0026amp; s2Map.containsKey(key) == false) sz++; for (String key: s2Map.keySet()) if (s2Map.get(key) == 1 \u0026amp;\u0026amp; s1Map.containsKey(key) == false) sz++; String[] ans = new String[sz]; int ptr = 0; for (String key: s1Map.keySet()) if (s1Map.get(key) == 1 \u0026amp;\u0026amp; s2Map.containsKey(key) == false) ans[ptr++] = key; for (String key: s2Map.keySet()) if (s2Map.get(key) == 1 \u0026amp;\u0026amp; s1Map.containsKey(key) == false) ans[ptr++] = key; return ans; } } 致谢 # 宫水三叶\n"},{"id":181,"href":"/docs/codes/0800-to-0899/0888.-Fair-Candy-Swap/","title":"0888. Fair Candy Swap","section":"0800 to 0899","content":" 0888. Fair Candy Swap # 题目 # 爱丽丝和鲍勃拥有不同总数量的糖果。给你两个数组 aliceSizes 和 bobSizes ,aliceSizes[i] 是爱丽丝拥有的第 i 盒糖果中的糖果数量,bobSizes[j] 是鲍勃拥有的第 j 盒糖果中的糖果数量。 两人想要互相交换一盒糖果,这样在交换之后,他们就可以拥有相同总数量的糖果。一个人拥有的糖果总数量是他们每盒糖果数量的总和。 返回一个整数数组 answer,其中 answer[0] 是爱丽丝必须交换的糖果盒中的糖果的数目,answer[1] 是鲍勃必须交换的糖果盒中的糖果的数目。如果存在多个答案,你可以返回其中 任何一个 。题目测试用例保证存在与输入对应的答案。 思路 # 哈希 # 代码 # 哈希 # class Solution { public int[] fairCandySwap(int[] aliceSizes, int[] bobSizes) { /** 设发生交换时,Alice和Bob拿出的糖果数量分别为x和y * sumAlice - x + y = sumBob - y + x * 成为两数之和问题 */ int nAlice = 0, nBob = 0; for (int num: aliceSizes) nAlice += num; for (int num: bobSizes) nBob += num; Set\u0026lt;Integer\u0026gt; set = new HashSet\u0026lt;\u0026gt;(); for (int num: aliceSizes) set.add(num); for (int num: bobSizes) { if (set.contains(num + (nAlice - nBob) / 2)) return new int[]{num + (nAlice - nBob) / 2, num}; } return new int[2]; } } 致谢 # 力扣官方题解\n"},{"id":182,"href":"/docs/codes/0800-to-0899/0896.-Monotonic-Array/","title":"0896. Monotonic Array","section":"0800 to 0899","content":" 0896. Monotonic Array # 题目 # 如果数组是单调递减或单调递增的,那么它是单调的。 如果对于所有 i \u0026lt;= j,nums[i] \u0026lt;= nums[j],那么数组 nums 是单调递增的。 如果对于所有 i \u0026lt;= j,nums[i]\u0026gt; = nums[j],那么数组 nums 是单调递减的。 当给定的数组 nums 是单调数组时返回 true,否则返回 false。 思路 # 模拟 # 代码 # 模拟 # class Solution { public boolean isMonotonic(int[] nums) { int monotonicity = 0; for (int i = 0; i \u0026lt; nums.length - 1; i++) { if (nums[i] == nums[i + 1]) continue; else if (monotonicity == 0) monotonicity = num[i] - nums[i + 1]; else if ((nums[i] - nums[i + 1]) * monotonicity \u0026lt; 0) return false; } return true; } } "},{"id":183,"href":"/docs/codes/0900-to-0999/0905.-Sort-Array-by-Parity/","title":"0905. Sort Array by Parity","section":"0900 to 0999","content":" 0905. Sort Array by Parity # 题目 # 给定整数数组 nums,将 nums 中偶数元素移动到数组前面,奇数元素移动到数组末端。 返回满足此条件的 任一数组 作为答案。 思路 # 双指针 # 代码 # 双指针 # class Solution { boolean isEven(int num) { return num % 2 == 0; } boolean isOdd(int num) { return num % 2 == 1; } public int[] sortArrayByParity(int[] nums) { int i = 0, j = nums.length - 1; while (i \u0026lt; j) { if (isEven(nums[i])) i += 1; else if (isOdd(nums[j])) j -= 1; else if (isEven(nums[i]) == isOdd(nums[j])) { nums[i] ^= nums[j]; nums[j] ^= nums[i]; nums[i] ^= nums[j]; i += 1; j -= 1; } } return nums; } } "},{"id":184,"href":"/docs/codes/0900-to-0999/0917.-Reverse-Only-Letters/","title":"0917. Reverse Only Letters","section":"0900 to 0999","content":" 0917. Reverse Only Letters # 题目 # 给定字符串 s ,根据下述规则反转字符串: 所有非英文字母保留在原有位置。 所有英文字母(小写或大写)位置反转。 返回反转后的 s 。 思路 # 双指针 # 代码 # 双指针 # class Solution { public String reverseOnlyLetters(String s) { char[] charArray = s.toCharArray(); int i = 0, j = s.length() - 1; while (i \u0026lt; j) { if (Character.isLetter(s.charAt(i)) == false) i++; else if (Character.isLetter(s.charAt(j)) == false) j--; else { char ch = charArray[i]; charArray[i] = charArray[j]; charArray[j] = charArray[i]; i++; j--; } } return String.valueOf(charArray); } } "},{"id":185,"href":"/docs/codes/0900-to-0999/0929.-Unique-Email-Addresses/","title":"0929. Unique Email Addresses","section":"0900 to 0999","content":" 0929. Unique Email Addresses # 题目 # 每个 有效电子邮件地址 都由一个 本地名 和一个 域名 组成,以 '@' 符号分隔。除小写字母之外,电子邮件地址还可以含有一个或多个 '.' 或 '+' 。 例如,在 [email protected]中, alice 是 本地名 ,而 leetcode.com 是 域名 。 如果在电子邮件地址的 本地名 部分中的某些字符之间添加句点('.'),则发往那里的邮件将会转发到本地名中没有点的同一地址。请注意,此规则 不适用于域名 。 例如,\u0026quot;[email protected]” 和 “[email protected]” 会转发到同一电子邮件地址。 如果在 本地名 中添加加号('+'),则会忽略第一个加号后面的所有内容。这允许过滤某些电子邮件。同样,此规则 不适用于域名 。 例如 [email protected] 将转发到 [email protected]。 可以同时使用这两个规则。 给你一个字符串数组 emails,我们会向每个 emails[i] 发送一封电子邮件。返回实际收到邮件的不同地址数目。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int numUniqueEmails(String[] emails) { Set\u0026lt;String\u0026gt; set = new HashSet\u0026lt;\u0026gt;(); for (String email: emails) { char[] charArray = email.toCharArray(); String vaildAddr = \u0026#34;\u0026#34;; /** user */ for (char ch: charArray) { if (ch == \u0026#39;.\u0026#39;) continue; if (ch == \u0026#39;+\u0026#39;) break; if (ch == \u0026#39;@\u0026#39;) break; vaildAddr += String.valueOf(ch); } /** hostname */ boolean flag = false; for (char ch: charArray) { if (ch == \u0026#39;@\u0026#39;) flag = true; if (flag) vaildAddr += String.valueOf(ch); } set.add(vaildAddr); } return set.size(); } } 致谢 # 宫水三叶\n"},{"id":186,"href":"/docs/codes/0900-to-0999/0933.-Number-of-Recent-Calls/","title":"0933. Number of Recent Calls","section":"0900 to 0999","content":" 933. Number of Recent Calls # 题目 # 写一个 RecentCounter 类来计算特定时间范围内最近的请求。\n请你实现 RecentCounter 类:\nRecentCounter() 初始化计数器,请求数为 0 。 int ping(int t) 在时间 t 添加一个新请求,其中 t 表示以毫秒为单位的某个时间,并返回过去 3000 毫秒内发生的所有请求数(包括新请求)。确切地说,返回在 [t-3000, t] 内发生的请求数。 每次对 ping 的调用都使用比之前更大的 t 值。 思路 # 队列 # 代码 # 队列 # class RecentCounter { private Queue\u0026lt;Integer\u0026gt; queue; public RecentCounter() { this.queue = new LinkedList\u0026lt;\u0026gt;(); } public int ping(int t) { queue.offer(t); while (queue.peek() \u0026lt; t - 3000) queue.poll(); return queue.size(); } } "},{"id":187,"href":"/docs/codes/0900-to-0999/0953.-Verifying-an-Alien-Dictionary/","title":"0953. Verifying an Alien Dictionary","section":"0900 to 0999","content":" 0953. Verifying an Alien Dictionary # 题目 # 某种外星语也使用英文小写字母,但可能顺序 order 不同。字母表的顺序(order)是一些小写字母的排列。 给定一组用外星语书写的单词 words,以及其字母表的顺序 order,只有当给定的单词在这种外星语中按字典序排列时,返回 true;否则,返回 false。 思路 # 模拟 # 自定义排序 # 代码 # 模拟 # class Solution { public boolean compareWords(String word1, String word2, Map\u0026lt;Character, Integer\u0026gt; map) { int ptr1 = 0, ptr2 = 0; while (ptr1 \u0026lt; word1.length() \u0026amp;\u0026amp; ptr2 \u0026lt; word2.length()) { int order1 = map.get(word1.charAt(ptr1)), order2 = map.get(word2.charAt(ptr2)); if (order1 \u0026gt; order2) return false; if (order1 \u0026lt; order2) return true; ptr1++; ptr2++; } return ptr1 == word1.length(); } public boolean isAlienSorted(String[] words, String order) { Map\u0026lt;Character, Integer\u0026gt; map = new HashMap\u0026lt;\u0026gt;(); for (int i = 0; i \u0026lt; order.length(); i++) map.put(order.charAt(i), i); boolean ans = true; for (int i = 0; i + 1 \u0026lt; words.length; i++) ans \u0026amp;= compareWords(words[i], words[i+1], map); return ans; } } 致谢 # 宫水三叶\n"},{"id":188,"href":"/docs/codes/0900-to-0999/0965.-Univalued-Binary-Tree/","title":"0965. Univalued Binary Tree","section":"0900 to 0999","content":" 965. Univalued Binary Tree # 题目 # 如果二叉树的每个节点都具有相同的值,那么该二叉树就是 单值 二叉树。\n只有给定的树是单值二叉树时,才返回 true,否则返回 false。\n思路 # 代码 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public boolean preOrderTraversal(TreeNode root, int uniVal) { if (root == null) return true; if (root.val != uniVal) return false; return preOrderTraversal(root.left, uniVal) \u0026amp; preOrderTraversal(root.right, uniVal); } public boolean isUnivalTree(TreeNode root) { retur } } "},{"id":189,"href":"/docs/codes/0900-to-0999/0977.-Squares-of-A-Sorted-Array/","title":"0977. Squares of a Sorted Array","section":"0900 to 0999","content":" 0977. Squares of A Sorted Array # 题目 # 给定按 非递减顺序 排序的整型数组 nums,返回 每个数字的平方 组成的新数组,要求新数组也按 非递减顺序 排序。\n思路 # 双指针 # 代码 # 双指针 # class Solution { public int[] sortedSquares(int[] nums) { int[] ans = new int[nums.length]; int i = 0, j = nums.length - 1, ptr = nums.length - 1; while (i \u0026lt;= j) { int num = Math.abs(nums[i]) \u0026gt; Math.abs(nums[j]) ? nums[i++] : nums[j--]; ans[ptr--] = num * num; } return ans; } } 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":190,"href":"/docs/codes/0900-to-0999/0997.-Find-the-Town-Judge/","title":"0997. Find the Town Judge","section":"0900 to 0999","content":" 0997. Find the Town Judge # 题目 # 小镇中有n个人,按从1到n的顺序编号。传言称,这些人中有一个暗地里是小镇法官。 如果小镇法官真的存在,那么: 小镇法官不会信任任何人。 每个人(除了小镇法官)都信任这位小镇法官。 只有一个人同时满足前两条。 给定数组trust,其中 trust[i] = [ai, bi] 表示编号为 ai 的人信任编号为 bi 的人。 如果小镇法官存在,请返回该法官的编号。否则返回-1。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int findJudge(int n, int[][] trust) { int[] cntMyTrust = new int[n + 1], cntTrustMe = new int[n + 1]; for (int[] pair: trust) { cntMyTrust[pair[0]]++; cntTrustMe[pair[1]]++; } for (int i = 1; i \u0026lt;= n; i++) { if (cntMyTrust[i] == 0 \u0026amp;\u0026amp; cntTrustMe[i] == n - 1) return i; } return -1; } } "},{"id":191,"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":192,"href":"/docs/codes/1000-to-1099/1021.-Remove-Outermost-Parentheses/","title":"1021. Remove Outermost Parentheses","section":"1000 to 1099","content":" 1021. Remove Outermost Parentheses # 题目 # 有效括号字符串为空 \u0026quot;\u0026quot;、\u0026quot;(\u0026quot; + A + \u0026quot;)\u0026quot; 或 A + B ,其中 A 和 B 都是有效的括号字符串,+ 代表字符串的连接。 例如,\u0026quot;\u0026quot;,\u0026quot;()\u0026quot;,\u0026quot;(())()\u0026quot; 和 \u0026quot;(()(()))\u0026quot; 都是有效的括号字符串。 如果有效字符串 s 非空,且不存在将其拆分为 s = A + B 的方法,我们称其为原语(primitive),其中 A 和 B 都是非空有效括号字符串。 给出一个非空有效字符串 s,考虑将其进行原语化分解,使得:s = P_1 + P_2 + ... + P_k,其中 P_i 是有效括号字符串原语。 对 s 进行原语化分解,删除分解中每个原语字符串的最外层括号,返回 s 。 思路 # 模拟 # 代码 # 模拟 # class Solution { public String removeOuterParentheses(String s) { String ans = \u0026#34;\u0026#34;; int left = 0, right = 0; for (int i = 0, j = 0; j \u0026lt; s.length(); j++) { Character ch = s.charAt(j); if (ch == \u0026#39;(\u0026#39;) left++; else if (--left == 0) { ans += s.substring(i+1, j); i = j + 1; } } return ans; } } 致谢 # 宫水三叶\n"},{"id":193,"href":"/docs/codes/1000-to-1099/1037.-Valid-Boomerang/","title":"1037. Valid Boomerang","section":"1000 to 1099","content":" 1037. Valid Boomerang # 题目 # 给定一个数组 points ,其中 points[i] = [xi, yi] 表示 X-Y 平面上的一个点,如果这些点构成一个 回旋镖 则返回 true 。 回旋镖 定义为一组三个点,这些点 各不相同 且 不在一条直线上 。 思路 # 斜率 # 向量叉积 # 代码 # 斜率 # class Solution { public boolean isSame(int[] p, int[] q) { return p[0] == q[0] \u0026amp;\u0026amp; p[1] == q[1]; } public boolean isColinear(int[] p, int[] q, int[] r) { if (p[0] == q[0]) return p[0] == r[0]; return ((double)q[1] - p[1])) / (q[0] - p[0]) == ((double)r[1] - p[1]) / (r[0] - p[0]); } public boolean isBoomerang(int[][] points) { int[] p0 = points[0], p1 = points[1], p2 = points[2]; if (isSame(p0, p1) || isSame(p0, p2) || isSame(p1, p2)) return false; return isColinear(p0, p1, p2) == false; } } 向量叉积 # 致谢 # 宫水三叶\n"},{"id":194,"href":"/docs/codes/1000-to-1099/1047.-Remove-All-Adjacent-Duplicates-In-String/","title":"1047. Remove All Adjacent Duplicates in String","section":"1000 to 1099","content":" 1047. Remove All Adjacent Duplicates In String # 题目 # 给出由小写字母组成的字符串 S, 重复项删除操作会选择两个相邻且相同的字母,并删除它们。\n在 S 上反复执行重复项删除操作,直至无法继续删除。\n在完成所有重复项删除操作后返回最终的字符串。\n思路 # 代码 # class Solution { public String removeDuplicates(String s) { Stack\u0026lt;Character\u0026gt; stack = new Stack\u0026lt;\u0026gt;(); for (int i=0; i\u0026lt;s.length(); i++) { char item = s.charAt(i); if (stack.empty() == false \u0026amp;\u0026amp; stack.peek() == item) stack.pop(); else stack.push(item); } char[] unique = new char[stack.size()]; for (int i=unique.length-1; i\u0026gt;=0; i--) unique[i] = stack.pop(); return String.valueOf(unique); } } "},{"id":195,"href":"/docs/codes/1000-to-1099/1078.-Occurrences-After-Bigram/","title":"1078. Occurrences After Bigram","section":"1000 to 1099","content":" 1078. Occurrences After Bigram # 题目 # 给出第一个词 first 和第二个词 second,考虑在某些文本 text 中可能以 \u0026quot;first second third\u0026quot; 形式出现的情况,其中 second 紧随 first 出现,third 紧随 second 出现。 对于每种这样的情况,将第三个词 \u0026ldquo;third\u0026rdquo; 添加到答案中,并返回答案。 思路 # 模拟 # 代码 # 模拟 # class Solution { public String[] findOcurrences(String text, String first, String second) { List\u0026lt;String\u0026gt; ans = new LinkedList\u0026lt;\u0026gt;(); String[] words = text.split(\u0026#34; \u0026#34;); for (int i = 0; i \u0026lt; words.length - 2; i++) { if (words[i].equals(first) \u0026amp;\u0026amp; words[i+1].equals(second)) ans.add(words[i+2]); } return ans.toArray(new String[ans.size()]); } } 致谢 # 宫水三叶\n"},{"id":196,"href":"/docs/codes/1000-to-1099/1089.-Duplicate-Zeros/","title":"1089. Duplicate Zeros","section":"1000 to 1099","content":" 1089. Duplicate Zeros # 题目 # 给定长度固定的整数数组 arr,将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。 注:不要在超过该数组长度的位置写入元素。对输入数组 原地 修改,不要从函数返回任何值。 思路 # 双指针 # 代码 # 双指针 # class Solution { public void duplicateZeros(int[] arr) { /** 1. 由于复写零的存在,只需要不超过arr.length个原始数组元素即可将arr填满,首先确定需要多少个元素将arr填满 */ int sum = 0, ptr = -1; while (sum \u0026lt; arr.length) { ptr++; if (arr[ptr] == 0) sum += 2; else dum += 1; } /** 2. sum的最终取值存在arr.length和arr.length+1两种情况 */ /** 3. 从后向前填充数组 */ for (int i = arr.length - 1; ptr \u0026gt; -1; ) { if (arr[ptr] == 0 \u0026amp;\u0026amp; sum \u0026lt;= arr.length) { arr[i] = arr[i-1] = 0; i -= 2; } else { sum -= 1; arr[i] = arr[ptr]; i -= 1; } ptr -= 1; } } } "},{"id":197,"href":"/docs/codes/1100-to-1199/1108.-Defanging-an-IP-Address/","title":"1108. Defanging an IP Address","section":"1100 to 1199","content":" 1108. Defanging an IP Address # 题目 # 给定一个有效的IPV4地址address,返回这个IP地址的无效化版本。\n无效化IP地址,就是用\u0026quot;[.]\u0026quot;代替了每个\u0026quot;.\u0026quot;。\n思路 # 模拟 # 代码 # 模拟 # class Solution { public String defangIPaddr(String address) { char[] and = new char[address.length() + 6]; int ptrAns = 0, ptrAddress = 0; while (ptrAns \u0026lt; ans.length) { if (address.charAt(ptrAddress) != \u0026#39;.\u0026#39;) { ans[ptrAns++] = address.charAt(ptrAddress); } else { ans[ptrAns++] = \u0026#39;[\u0026#39;; ans[ptrAns++] = \u0026#39;.\u0026#39;; ans[ptrAns+=] = \u0026#39;]\u0026#39;; } ptrAddress++; } return String.valueOf(ans); } } "},{"id":198,"href":"/docs/codes/1100-to-1199/1137.-N-th-Tribonacci-Number/","title":"1137. N Th Tribonacci Number","section":"1100 to 1199","content":" 1137. N-th Tribonacci Number # 题目 # 泰波那契序列 Tn 定义如下:\nT0 = 0, T1 = 1, T2 = 1, 且在 n \u0026gt;= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2\n给你整数 n,请返回第 n 个泰波那契数 Tn 的值。\n模拟 # 代码 # 模拟 # class Solution { public int tribonacci(int n) { if (n == 0) return 0; if (n == 1) return 1; if (n == 2) return 1; int[] mem = new int[n+1]; mem[0] = 0; mem[1] = mem[2] = 1; for (int i = 3; i \u0026lt;= n; i++) mem[i] = mem[i-1]+mem[i-2]+mem[i-3]; return mem[n]; } } 致谢 # 宫水三叶\n"},{"id":199,"href":"/docs/codes/1100-to-1199/1154.-Day-of-the-Year/","title":"1154. Day of the Year","section":"1100 to 1199","content":" 1154. Day of the Year # 题目 # 给定字符串 date,按YYYY-MM-DD格式表示一个现行公元年法日期。\n返回该日期是当年的第几天。\n思路 # 模拟 # 打表 # 代码 # 模拟 # class Solution { public boolean isLeapYear(int year) { /** 能被4整除但不能被100整除的是闰年 * 能被400整除的是闰年 */ return (year % 4 == 0 \u0026amp;\u0026amp; year % 100 != 0) || year % 400 == 0; } public int dayOfYear(String date) { int year = Integer.parseInt(date.split(\u0026#34;-\u0026#34;)[0]); int month = Integer.parseInt(date.split(\u0026#34;-\u0026#34;)[1]); int day = Integer.parseInt(date.split(\u0026#34;-\u0026#34;)[2]); int[] days = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (isLeapYear(year)) days[1] += 1; int ans = 0; for (int i = 0; i \u0026lt; month - 1; i++) ans += days[i]; ans += day; return ans; } } 打表 # 致谢 # 宫水三叶\n"},{"id":200,"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":201,"href":"/docs/codes/1100-to-1199/1184.-Distance-Between-Bus-Stops/","title":"1184. Distance Between Bus Stops","section":"1100 to 1199","content":" 1184. Distance Between Bus Stops # 题目 # 环形公交路线上有 n 个站,按次序从 0 到 n - 1 进行编号。我们已知每一对相邻公交站之间的距离,distance[i] 表示编号为 i 的车站和编号为 (i + 1) % n 的车站之间的距离。\n环线上的公交车都可以按顺时针和逆时针的方向行驶。\n返回乘客从出发点 start 到目的地 destination 之间的最短距离。\n思路 # 模拟 # 代码 # 模拟 # class Solution { public int distanceBetweenBusStops(int[] distance, int start, int destination) { int res1 = 0, totalDist = 0; for (int i = Math.min(start, destination); i \u0026lt; Math.max(start, destination); i++) res1 += distance[i]; for (int dist: distance) totalDist += dist; return Math.min(res1, totalDist-res1); } } 致谢 # 宫水三叶\n"},{"id":202,"href":"/docs/codes/1100-to-1199/1185.-Day-of-the-Week/","title":"1185. Day of the Week","section":"1100 to 1199","content":" 1185. Day of the Week # 题目 # 给你一个日期,请你设计一个算法来判断它是对应一周中的哪一天。\n输入为三个整数:day、month 和 year,分别表示日、月、年。\n您返回的结果必须是这几个值中的一个 {\u0026quot;Sunday\u0026quot;, \u0026quot;Monday\u0026quot;, \u0026quot;Tuesday\u0026quot;, \u0026quot;Wednesday\u0026quot;, \u0026quot;Thursday\u0026quot;, \u0026quot;Friday\u0026quot;, \u0026quot;Saturday\u0026quot;}。\n思路 # 模拟 # 代码 # 模拟 # class Solution { public boolean isLeapYear(int year) { return (year % 4 == 0 \u0026amp;\u0026amp; year % 100 != 0) || year % 400 == 0; } public int[] dayOfMonths (int year) { int[] days = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (isLeapYear(year)) days[1]++; return days; } public String dayOfTheWeek(int day, int month, int year) { /** 1971/01/01 is Friday. */ /** 1. 推断出year/month/day这一天距离1971/01/01过去了多少days */ int days = 0; if (year == 1971) { /** 计算1971/month/day这一天距离1971/01/01过去了多少天 */ for(int i = 0; i \u0026lt; month - 1; i++) days += dayOfMonths(year)[i]; days += day - 1; } else { for (int i = 1971; i \u0026lt; year; i++) days += isLeapYear(i) ? 366 : 365; for (int i = 0; i \u0026lt; month - 1; i++) days += dayOfMonths(year)[i]; days += day - 1; } /** 2. 用days对7取模*/ switch (days % 7) { case 0 : return \u0026#34;Friday\u0026#34;; case 1 : return \u0026#34;Saturday\u0026#34;; case 2 : return \u0026#34;Sunday\u0026#34;; case 3 : return \u0026#34;Monday\u0026#34;; case 4 : return \u0026#34;Tuesday\u0026#34;; case 5 : return \u0026#34;Wednesday\u0026#34;; case 6 : return \u0026#34;Thursday\u0026#34;; } /** 3. 返回答案 */ return \u0026#34;\u0026#34;; } } 致谢 # 宫水三叶\nfater\n"},{"id":203,"href":"/docs/codes/1100-to-1199/1189.-Maximum-Number-of-Balloons/","title":"1189. Maximum Number of Balloons","section":"1100 to 1199","content":" 1189. Maximum Number of Balloons # 题目 # 给你一个字符串 text,你需要使用 text 中的字母来拼凑尽可能多的单词 \u0026ldquo;balloon\u0026rdquo;(气球)。\n字符串 text 中的每个字母最多只能被使用一次。请你返回最多可以拼凑出多少个单词 \u0026ldquo;balloon\u0026rdquo;。\n思路 # 模拟 # 代码 # 模拟 # class Solution { public int maxNumberOfBalloons(String text) { /** balon */ int[] count = new int[5]; for (int i = 0; i \u0026lt; text.length(); i++) { switch (text.charAt(i)) { case \u0026#39;b\u0026#39; : count[0]++; break; case \u0026#39;a\u0026#39; : count[1]++; break; case \u0026#39;l\u0026#39; : count[2]++; break; case \u0026#39;o\u0026#39; : count[3]++; break; case \u0026#39;n\u0026#39; : count[4]++; break; } } int ans = Math.min(count[0], count[1]); ans = Math.min(ans, count[2] / 2); ans = Math.min(ans, count[3] / 2); ans = Math.min(ans, count[4]); return ans; } } "},{"id":204,"href":"/docs/codes/1200-to-1299/1206.-Design-SkipList/","title":"1206. Design Skip List","section":"1200 to 1299","content":" 1206. Design SkipList # 题目 # 不使用任何库函数,设计一个 跳表 。\n跳表 是在 O(log(n)) 时间内完成增加、删除、搜索操作的数据结构。跳表相比于AVL树和红黑树,性能与之相当。且跳表的代码长度相较下更短,其设计思想与链表相似。\n跳表中有很多层,每一层是一个短的链表。在第一层的作用下,增加、删除和搜索操作的时间复杂度不超过 O(n)。跳表的每一个操作的平均时间复杂度是 O(log(n)),空间复杂度是 O(n)。,\n本题的设计应该包含以下函数:\nbool search(int target):返回 target 是否存在于跳表中。 void add(int num):插入一个元素到跳表。 bool erase(int num):在跳表中删除一个值,如果 num 不存在,直接返回 false。如果存在多个 num,删除其中任意一个即可。 Tips 跳表中可能存在多个相同的值,所设计的跳表需要处理这种情况。\n思路 # 代码 # class Skiplist { private int MAX_LEVEL = 10; private class SkipNode { public int val; public SkipNode[] next; SkipNode(int val) { this.val = val; this.next = new SkipNode[this.MAX_LEVEL]; } } private SkipNode sentinel; private Random random; public Skiplist() { this.sentinel = new SkipNode(-1); this.random = new Random(); } public void find(int val, SkipNode[] prev) { SkipNode ptr = sentinel; for (int level = this.MAX_LEVEL-1; level \u0026gt;= 0; level -= 1) { while (ptr.next[level] != null \u0026amp;\u0026amp; ptr.next[level].val \u0026lt; val) ptr = ptr.next[level]; prev[level] = ptr; } } public boolean search(int target) { SkipNode[] prev = new SkipNode[this.MAX_LEVEL]; find(target, prev); return prev[0].next[0] != null \u0026amp;\u0026amp; prev[0].next[0].val == target; } public void add(int num) { SkipNode[] prev = new SkipNode[this.MAX_LEVEL]; find(num, prev); SkipNode node = new SkipNode(num); for (int level = 0; level \u0026lt; this.MAX_LEVEL; level += 1) { node.next[level] = prev[level].next; prev[level].next = node; if (this.random.nextInt(2) == 0) break; } } public boolean erase(int num) { SkipNode[] prev = new SkipNode[this.MAX_LEVEL]; find(num, prev); SkipNode node = prev[0].next[0]; if (node == null || node.val != num) return false; for (int level = 0; level \u0026lt; this.MAX_LEVEL; level += 1) { if (prev[level].next[level] == node) { prev[level].next[level] = node.next[level]; } } return true; } } 致谢 # 宫水三叶 力扣官方题解 赵陌陌丶 Skip lists: a probabilistic alternative to balanced trees "},{"id":205,"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":206,"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":207,"href":"/docs/codes/1200-to-1299/1295.-Find-Numbers-with-Even-Number-of-Digits/","title":"1295. Find Numbers With Even Number of Digits","section":"1200 to 1299","content":" 1295. Find Numbers with Even Number of Digits # 题目 # 给定整数数组 nums,返回其中位数为 偶数 的数字的个数。 思路 # 模拟 # 数学 # 代码 # 模拟 # class Solution { public int count(int num) { int ans = 0; while (num \u0026gt; 0) { ans++; num /= 10; } return ans; } public int findNumbers(int[] nums) { int ans = 0; for (int num: nums) ans += ocunt(num) % 2 == 0 ? 1 : 0; return ans; } } 数学 # 致谢 # 力扣官方题解\n"},{"id":208,"href":"/docs/codes/1300-to-1399/1342.-Number-of-Steps-to-Reduce-a-Number-to-Zero/","title":"1342. Number of Steps to Reduce a Number to Zero","section":"1300 to 1399","content":" 1342. Number of Steps to Reduce a Number to Zero # 题目 # 给你一个非负整数 nums,返回将它变为 0 所需要的步数。\n如果当前数字是偶数,则将它除以 2,否则减去 1。\n思路 # 模拟 数学 + 位运算 可从如下角度考虑模拟过程: 若 nums 最低位非 1,则进行右移 若 nums 最低位为 1,则消减最低位的 1 总操作次数等于: 最高位 1 的右移次数 + nums 的二进制表示中 1 的个数 代码 # 模拟 # class Solution { public int numberOfSteps(int num) { int step = 0; while (num != 0 \u0026amp;\u0026amp; ++step \u0026gt; 0) num = (num \u0026amp; 1 == 0) ? num \u0026gt;\u0026gt; 1 : num - 1; return step; } } 数学 + 位运算 # class Solution { public int numberOfSteps(int num) { /** 定位最高位1的右移次数 */ int numShift = 0; for (int i = 31; i \u0026gt;= 0; i--) { if ( ((num \u0026gt;\u0026gt; i) \u0026amp; 1) == 0 ) continue; numShift += 1; break; } /** 计数num的二进制表示中1的个数 */ int numOnes = 0; for (int i = 31; i \u0026gt;= 0; i--) { if ( ((num \u0026gt;\u0026gt; i) \u0026amp; 1) == 0 ) continue; numOnes += 1; } /** 将数字变为 0 的操作次数 等同于最高位1的右移次数 + 二进制表示中1的个数 */ return numShift + numOnes; } } 致谢 # 宫水三叶 无魂雨 "},{"id":209,"href":"/docs/codes/1300-to-1399/1374.-Generate-a-String-With-Characters-That-Have-Odd-Counts/","title":"1374. Generate a String With Characters That Have Odd Counts","section":"1300 to 1399","content":" 1374. Generate a String With Characters That Have Odd Counts # 题目 # 给你一个整数 n,请你返回一个含 n 个字符的字符串,其中每种字符在该字符串中都恰好出现 奇数次 。 返回的字符串必须只含小写英文字母。如果存在多个满足题目要求的字符串,则返回其中任意一个即可。 思路 # 模拟 # 代码 # 模拟 # class Solution { public String generateTheString(int n) { String ans = \u0026#34;\u0026#34;; if (n % 2 == 0) { for (int i = 0; i \u0026lt; n - 1; i++) ans += \u0026#34;a\u0026#34;; ans += \u0026#34;b\u0026#34;; } else { for (int i = 0; i \u0026lt; n; i++) ans += \u0026#34;a\u0026#34;; } return ans; } } 致谢 # 宫水三叶\n"},{"id":210,"href":"/docs/codes/1300-to-1399/1380.-Lucky-Numbers-in-a-Matrix/","title":"1380. Lucky Numbers in a Matrix","section":"1300 to 1399","content":" 1380. Lucky Numbers in a Matrix # 题目 # 给你一个 m * n 的矩阵,矩阵中的数字 各不相同 。请你按 任意 顺序返回矩阵中的所有幸运数。 幸运数 是指矩阵中满足同时下列两个条件的元素: 在同一行的所有元素中最小 在同一列的所有元素中最大 思路 # 模拟 # 代码 # 模拟 # class Solution { public List\u0026lt;Integer\u0026gt; luckyNumbers (int[][] matrix) { List\u0026lt;Integer\u0026gt; ans = new LinkedList\u0026lt;\u0026gt;(); int M = matrix.length, N = matrix[0].length; int[] minimumRow = new int[M], maximumCol = new int[N]; Arrays.fill(minimumRow, Integer.MAX_VALUE); Arrays.fill(maximumCol, Integer.MIN_VALUE); for (int i = 0; i \u0026lt; M; i++) { for (int j = 0; j \u0026lt; N; j++) { minimumRow[i] = Math.min(minimumRow[i], matrix[i][j]); maximumCol[j] = Math.max(maximumCol[j], matrix[i][j]); } } for (int i = 0; i \u0026lt; M; i++) { for (int j = 0; j \u0026lt; N; j++) { if (matrix[i][j] == minimumRow[i] \u0026amp;\u0026amp; matrix[i][j] == maximumCol[j]) ans.add(matrix[i][j]); } } return ans; } } "},{"id":211,"href":"/docs/codes/1300-to-1399/1394.-Find-Lucky-Integer-in-an-Array/","title":"1394. Find Lucky Integer in an Array","section":"1300 to 1399","content":" 1394. Find Lucky Integer in an Array # 题目 # 在整数数组中,如果一个整数的出现频次和它的数值大小相等,则称此整数为 幸运数。\n给定整数数组 arr,从中找出并返回一个幸运数。\n若数组中存在多个幸运数,则返回最大的那个。若数组中不含幸运数,返回 -1。\n思路 # 代码 # class Solution { public int findLucky(int[] arr) { Map\u0026lt;Integer, Integer\u0026gt; map = new HashMap\u0026lt;\u0026gt;(); for (int num: arr) map.put(num, map.getOrDefault(num, 0) + 1); int maxLucky = -1; for (Integer x: map.keySet()) if (map.get(x) == x) maxLucky = Math.max(x, maxLucky); return maxLucky; } } "},{"id":212,"href":"/docs/codes/1400-to-1499/1413.-Minimum-Value-to-Get-Positive-Step-by-Step-Sum/","title":"1413. Minimum Value to Get Positive Step by Step Sum","section":"1400 to 1499","content":" 1413. Minimum Value to Get Positive Step by Step Sum # 题目 # 给你一个整数数组 nums 。你可以选定任意的 正数 startValue 作为初始值。\n你需要从左到右遍历 nums 数组,并将 startValue 依次累加上 nums 数组中的值。\n请你在确保累加和始终大于等于 1 的前提下,选出一个最小的 正数 作为 startValue 。\n思路 # 模拟 # 代码 # 模拟 # class Solution { public int minStartValue(int[] nums) { int ans = 1, prefixSum = 1; for (int num: nums) { prefixSum += num; if (prefixSum \u0026lt; 1) { ans += 1 - prefixSum; prefixSum = 1; } } return ans; } } 致谢 # 宫水三叶\n"},{"id":213,"href":"/docs/codes/1400-to-1499/1417.-Reformat-The-String/","title":"1417. Reformat the String","section":"1400 to 1499","content":" 1417. Reformat The String # 题目 # 给你一个混合了数字和字母的字符串 s,其中的字母均为小写英文字母。\n请你将该字符串重新格式化,使得任意两个相邻字符的类型都不同。也就是说,字母后面应该跟着数字,而数字后面应该跟着字母。\n请你返回 重新格式化后 的字符串;如果无法按要求重新格式化,则返回一个 空字符串 。\n思路 # 模拟 # 代码 # 模拟 # class Solution { public String reformat(String s) { LinkedList\u0026lt;Character\u0026gt; charList = new LinkedList\u0026lt;\u0026gt;(), digitList = new LinkedList\u0026lt;\u0026gt;(); for (int i = 0; i \u0026lt; s.length(); i++) { char ch = s.charAt(i); if (Character.isDigit(ch)) digitList.add(ch); else charList.add(ch); } if (Math.abs(charList.size() - digitList.size()) \u0026gt; 1) return \u0026#34;\u0026#34;; List\u0026lt;Character\u0026gt; Long = charList.size() \u0026gt;= digitList.size() ? charList : digitList; List\u0026lt;Character\u0026gt; Short = charList.size() \u0026lt; digitList.size() ? charList : digitList; char[] ans = new char[s.length()]; int ptr = 0, ptrLong = 0, ptrShort = 0; while (ptr \u0026lt; ans.length) { ans[ptr++] = Long.get(ptrLong++); if (ptrShort \u0026lt; Short.size()) ans[ptr++] = Short.get(ptrShort++); } return String.valueOf(ans); } } 致谢 # 宫水三叶\n"},{"id":214,"href":"/docs/codes/1400-to-1499/1422.-Maximum-Score-After-Splitting-a-String/","title":"1422. Maximum Score After Splitting a String","section":"1400 to 1499","content":" 1422. Maximum Score After Splitting a String # 题目 # 给你一个由若干 0 和 1 组成的字符串 s ,请你计算并返回将该字符串分割成两个 非空 子字符串(即 左 子字符串和 右 子字符串)所能获得的最大得分。\n「分割字符串的得分」为 左 子字符串中 0 的数量加上 右 子字符串中 1 的数量。\n思路 # 模拟 # 代码 # 模拟 # class Solution { public int maxScore(String s) { int N = s.length(); /** 令zeros[i]记录截止下标i处字符串中共出现了多少个0 */ int[] zeros = new int[N], ones = new int[N]; for (int i = 0; i \u0026lt; N; i++) { switch (s.charAt(i)) { case \u0026#39;0\u0026#39;: zeros[i] = i == 0 ? 1 : zeros[i-1] + 1; ones[i] = i == 0 ? 0 : ones[i-1]; break; case \u0026#39;1\u0026#39;: ones[i] = i == 0 ? 1 : ones[i-1] + 1; zeros[i] = i == 0 ? 0 : zeros[i-1]; break; } } int ans = 0; for (int i = 0; i \u0026lt; N-1; i++) { ans = Math.max(ans, zeros[i] + ones[N-1]-ones[i]); } return ans; } } 致谢 # 宫水三叶\n"},{"id":215,"href":"/docs/codes/1400-to-1499/1436.-Destination-City/","title":"1436. Destination City","section":"1400 to 1499","content":" 1436. Destination City # 题目 # 给你一份旅游线路图,该线路图中的旅行线路用数组 paths 表示,其中 paths[i] = [cityAi, cityBi] 表示该线路将会从 cityAi 直接前往 cityBi 。请你找出这次旅行的终点站,即没有任何可以通往其他城市的线路的城市*。*\n题目数据保证线路图会形成一条不存在循环的线路,因此恰有一个旅行终点站。\n思路 # 模拟+哈希 # 代码 # 模拟+哈希 # class Solution { public String destCity (List\u0026lt;List\u0026lt;String\u0026gt;\u0026gt; paths) { Set\u0026lt;String\u0026gt; start = new HashSet\u0026lt;\u0026gt;(); Set\u0026lt;String\u0026gt; end = new HashSet\u0026lt;\u0026gt;(); for (List\u0026lt;String\u0026gt; path: paths) { /** consider start */ start.add(path.get(0)); if (end.contains(path.get(0))) end.remove(path.get(0)); /** consider end */ if (start.contains(path.get(1)) == false) end.add(path.get(1)); else if (end.contains(path.get(1))) end.remove(path.get(1)); } String ans = \u0026#34;\u0026#34;; for (String str: end) ans = str; return ans; } } 致谢 # 宫水三叶\n"},{"id":216,"href":"/docs/codes/1400-to-1499/1446.-Consecutive-Characters/","title":"1446. Consecutive Characters","section":"1400 to 1499","content":" 1446. Consecutive Characters # 题目 # 字符串的**「能量」**定义为:只包含一种字符的最长非空子字符串的长度。\n返回字符串 s 的 能量。\n思路 # 模拟 # 代码 # 模拟 # class Solution { public int maxPower(String s) { int maxPower = 1, power = 1; char ch = s.charAt(0); for (int i = 1; i \u0026lt; s.length(); i++) { if (s.charAt(i) == ch) { power += 1; maxPower = Math.max(power, maxPower); } else { power += 1; ch = s.charAt(i); } } return maxPower; } } "},{"id":217,"href":"/docs/codes/1400-to-1499/1455.-Check-If-a-Word-Occurs-As-a-Prefix-of-Any-Word-in-a-Sentence/","title":"1455. Check if a Word Occurs as a Prefix of Any Word in a Sentence","section":"1400 to 1499","content":" 1455. Check If a Word Occurs As a Prefix of Any Word in a Sentence # 题目 # 给定字符串 sentence 并指定检索词为 searchWord ,句子由 空格 分隔的单词组成。 检查检索词 searchWord 是否为句子 sentence 中任意单词的前缀。 如果 searchWord 是某一个单词的前缀,则返回句子 sentence 中该单词所对应的下标(下标从 1 开始)。 如果 searchWord 是多个单词的前缀,则返回匹配的第一个单词的下标(最小下标)。 如果 searchWord 不是任何单词的前缀,则返回 -1 。 字符串 s 的 前缀 是 s 的任何前导连续子字符串。 思路 # 双指针 # 代码 # 双指针 # class Solution { public int isPrefixOfWord(String sentence, String searchWord) { int ptr1 = 0, ans = 0; while (ptr1 \u0026lt; sentence.length()) { int ptr2 = ptr1; ans += 1; /** 检查当前词的匹配状态 */ while (ptr2 \u0026lt; ptr1 + searchWord.length() \u0026amp;\u0026amp; sentence.charAt(ptr2) == searchWord.charAt(ptr2 - ptr1)) ptr2 += 1; if (ptr2 == ptr1 + searchWord.length()) return ans; /** 若失配,检查下一个词的匹配状态 */ else { ptr1 = ptr2; while (ptr1 \u0026lt; sentence.length() \u0026amp;\u0026amp; sentence.charAt(ptr1) != \u0026#39; \u0026#39;) ptr1 += 1; ptr1 += 1; } } return -1; } } "},{"id":218,"href":"/docs/codes/1400-to-1499/1464.-Maximum-Product-of-Two-Elements-in-an-Array/","title":"1464. Maximum Product of Two Elements in an Array","section":"1400 to 1499","content":" 1464. Maximum Product of Two Elements in an Array # 题目 # 给定一个整数数组nums,选择数组的两个不同下表i和j,使(nums[i]-1)*(nums[j]-1)取得最大值。 计算并返回该式的最大值。 2 \u0026lt;= nums.length \u0026lt;= 500 1 \u0026lt;= nums[i] \u0026lt;= 10^3 思路 # 模拟 # 代码 # 模拟 # class Solution { public int maxProduct(int[] nums) { int[] ans = new int[2]; for (int num: nums) { if (ans[0] == 0) ans[0] = num; else { if (num \u0026gt;= ans[0]) { ans[1] = ans[0]; ans[0] = num; } else if (num \u0026gt;= ans[1]) ans[1] = num; } } return (ans[0] - 1) * (ans[1] - 1); } } 致谢 # 宫水三叶\n"},{"id":219,"href":"/docs/codes/1400-to-1499/1470.-Shuffle-the-Array/","title":"1470. Shuffle the Array","section":"1400 to 1499","content":" 1470. Shuffle the Array # 题目 # 给定数组 nums,数组中有 2n 个元素,按[x1,x2,...,xn,y1,y2,...,yn] 的格式排列。 将数组按 [x1,y1,x2,y2,...,xn,yn] 格式重新排列,返回重排后的数组。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int[] shuffle(int[] nums, int n) { int[] ans = new int[nums.length]; for (int i = 0; i \u0026lt; n; i++) { ans[2*i] = nums[i]; ans[2*i+1] = nums[i+n]; } return ans; } } "},{"id":220,"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":221,"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":222,"href":"/docs/codes/1400-to-1499/1480.-Running-Sum-of-1d-Array/","title":"1480. Running Sum of 1d Array","section":"1400 to 1499","content":" 1480. Running Sum of 1d Array # 题目 # 数组「动态和」的计算公式为:runningSum[i] = sum(nums[0]…nums[i]) 。\n给定数组 nums 。返回 nums 的动态和。\n思路 # 模拟 # 代码 # 模拟 # class Solution { public int[] runningSum(int[] nums) { for (int i = 1; i \u0026lt; nums.length; i++) nums[i] += nums[i-1]; return nums; } } "},{"id":223,"href":"/docs/codes/1400-to-1499/1486.-XOR-Operation-in-an-Array/","title":"1486. Xor Operation in an Array","section":"1400 to 1499","content":" 1486. XOR Operation in an Array # 题目 # 给定两个整数,n 和 start。\n数组 nums 定义为: nums[i] = start + 2*i (下标从0开始)且 n == nums.length。\n返回 nums 中所有元素按位异或 (XOR) 后得到的结果。\n思路 # 代码 # class Solution { public int xorOperation(int n, int start) { int xor = 0; for (int i = 0; i \u0026lt; n; i++) xor ^= start + 2 * i; return xor; } } "},{"id":224,"href":"/docs/codes/1400-to-1499/1491.-Average-Salary-Excluding-the-Minimum-and-Maximum-Salary/","title":"1491. Average Salary Excluding the Minimum and Maximum Salary","section":"1400 to 1499","content":" 1491. Average Salary Excluding the Minimum and Maximum Salary # 题目 # 给定整数数组 salary,数组中每个数都是唯一的,其中 salary[i] 是第 i 个员工的工资。 返回去掉最低工资和最高工资后,剩下员工工资的平均值。 思路 # 模拟 # 代码 # 模拟 # class Solution { public double average(int[] salary) { int minSalary = Integer.MAX_VALUE, maxSalary = Integer.MIN_VALUE, sum = 0; for (int num: salary) { minSalary = Math.min(minSalary, num); maxSalary = Math.max(maxSalary, num); sum += num; } return (double)(sum - minSalary - maxSalary) / (salary.length - 2); } } "},{"id":225,"href":"/docs/codes/1500-to-1599/1518.-Water-Bottles/","title":"1518. Water Bottles","section":"1500 to 1599","content":" 1518. Water Bottles # 题目 # 超市正在促销,你可以用 numExchange 个空水瓶从超市兑换一瓶水。最开始,你一共购入了 numBottles 瓶水。 如果喝掉了水瓶中的水,那么水瓶就会变成空的。 给你两个整数 numBottles 和 numExchange ,返回你 最多 可以喝到多少瓶水。 思路 # 模拟 # 数学 # 代码 # 模拟 # class Solution { public int numWaterBottles(int numBottles, int numExchange) { int drink = numBottles, empty = numBottles; while (empty / numExchange != 0) { drink += empty / numExchange; empty = empty / numExchange + empty % numExchange; } return drink; } } 数学 # 致谢 # 宫水三叶\n"},{"id":226,"href":"/docs/codes/1500-to-1599/1576.-Replace-All-s-to-Avoid-Consecutive-Repeating-Characters/","title":"1576. Replace All ?'S to Avoid Consecutive Repeating Characters","section":"1500 to 1599","content":" 1576. Replace All ?\u0026rsquo;s to Avoid Consecutive Repeating Characters # 题目 # 给定一个仅包含小写英文字母和 '?' 字符的字符串 s,将所有的 '?' 转换为若干小写字母,使最终的字符串不包含任何 连续重复 的字符。 不能 修改非 '?' 字符。 除 '?' 字符 之外,不存在连续重复的字符。 在完成所有转换(可能无需转换)后返回最终的字符串。如果有多个解决方案,请返回其中任何一个。 思路 # 模拟 # 代码 # 模拟 # class Solution { private Random random = new Random(); public Character findCandidate(Character ban1, Character ban2) { Character ans = \u0026#39;a\u0026#39;; while (ans == ban1 || ans == ban2) { ans = (char)(\u0026#39;a\u0026#39; + this.random.nextInt(26)); } return ans; } public String modifyString(String s) { char[] charArray = s.toCharArray(); for (int i = 0; i \u0026lt; charArray.length; i++) { if (charArray[i] == \u0026#39;?\u0026#39;) { if (i == 0) { if (i+1 \u0026lt; charArray.length) charArray[i] = findCandidate(charArray[i+1], null); else charArray[i] = \u0026#39;a\u0026#39;; } else if (i == charArray.length - 1) charArray[i] = findCandidate(charArray[i-1], null); else charArray[i] = findCandidate(charArray[i-1], charArray[i+1]); } } return String.valueOf(charArray); } } 致谢 # 宫水三叶\n"},{"id":227,"href":"/docs/codes/1500-to-1599/1582.-Special-Positions-in-a-Binary-Matrix/","title":"1582. Special Positions in a Binary Matrix","section":"1500 to 1599","content":" 1582. Special Positions in a Binary Matrix # 题目 # 给你一个大小为 rows x cols 的矩阵 mat,其中 mat[i][j] 是 0 或 1,请返回 矩阵 mat 中特殊位置的数目 。 特殊位置 定义:如果 mat[i][j] == 1 并且第 i 行和第 j 列中的所有其他元素均为 0(行和列的下标均 从 0 开始 ),则位置 (i, j) 被称为特殊位置。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int numSpecial(int[][] mat) { Map\u0026lt;Integer, Integer\u0026gt; cntRows = new HashMap\u0026lt;\u0026gt;(); Map\u0026lt;Integer, Integer\u0026gt; cntCols = new HashMap\u0026lt;\u0026gt;(); for (int i = 0; i \u0026lt; mat.length; i++) { int sum = 0; for (int num: mat[i]) sum += num; if (sum \u0026gt; 0) cntRows.put(i, sum); } for (int j = 0; j \u0026lt; mat[0].length; j++) { int sum = 0; for (int i = 0; i \u0026lt; mat.length; i++) sum += mat[i][j]; if (sum \u0026gt; 0) cntCols.put(j, sum); } int ans = 0; for (int i = 0; i \u0026lt; mat.length; i++) { for (int j = 0; j \u0026lt; mat[0].length; j++) { if (mat[i][j] == 1 \u0026amp;\u0026amp; cntRows.get(i) == 1 \u0026amp;\u0026amp; cntCols.get(j) == 1) ans++; } } return ans; } } 致谢 # 宫水三叶\n"},{"id":228,"href":"/docs/codes/1600-to-1699/1608.-Special-Array-With-X-Elements-Greater-Than-or-Equal-X/","title":"1608. Special Array With X Elements Greater Than or Equal X","section":"1600 to 1699","content":" 1608. Special Array With X Elements Greater Than or Equal X # 题目 # 给你一个非负整数数组 nums 。如果存在一个数 x ,使得 nums 中恰好有 x 个元素 大于或者等于 x ,那么就称 nums 是一个 特殊数组 ,而 x 是该数组的 特征值 。\n注意: x 不必 是 nums 的中的元素。\n如果数组 nums 是一个 特殊数组 ,请返回它的特征值 x 。否则,返回 -1 。可以证明的是,如果 nums 是特殊数组,那么其特征值 x 是 唯一的 。\n思路 # 排序 # 代码 # 排序 # class Solution { public int specialArray(int[] nums) { Arrays.sort(nums); for (int k = nums.length; k \u0026gt;= 1; k--) { boolean flag = true; flag \u0026amp;= nums[nums.length-k] \u0026gt;= k; flag \u0026amp;= nums.length - (k+1) \u0026lt; 0 || nums[nums.length - k - 1] \u0026lt; k; if (flag == true) return k; } return -1; } } 致谢 # 宫水三叶\n"},{"id":229,"href":"/docs/codes/1600-to-1699/1614.-Maximum-Nesting-Depth-of-the-Parentheses/","title":"1614. Maximum Nesting Depth of the Parentheses","section":"1600 to 1699","content":" 1614. Maximum Nesting Depth of the Parentheses # 题目 # 有效括号字符串满足下列条件之一\n字符串是一个空字符串 \u0026quot;\u0026quot;,或者是一个不为 \u0026quot;(\u0026quot; 或 \u0026quot;)\u0026quot; 的单字符。\n字符串可以写为 AB(A 与 B 字符串连接),其中 A 和 B 都是 有效括号字符串 。\n字符串可以写为 (A),其中 A 是一个 有效括号字符串 。\n有效括号字符串 S 的 嵌套深度 depth(S) 定义为:\ndepth(\u0026quot;\u0026quot;) = 0\ndepth(C) = 0,其中 C 是单个字符的字符串,且该字符不是 \u0026quot;(\u0026quot; 或者 \u0026quot;)\u0026quot;\ndepth(A + B) = max(depth(A), depth(B)),其中 A 和 B 都是 有效括号字符串\ndepth(\u0026quot;(\u0026quot; + A + \u0026quot;)\u0026quot;) = 1 + depth(A),其中 A 是一个 有效括号字符串\n例如:\u0026quot;\u0026quot;、\u0026quot;()()\u0026quot;、\u0026quot;()(()())\u0026quot; 都是 有效括号字符串(嵌套深度分别为 0、1、2),而 \u0026quot;)(\u0026quot; 、\u0026quot;(()\u0026quot; 都不是 有效括号字符串 。\n给定 有效括号字符串 s,返回字符串的 s 嵌套深度 。\n思路 # 栈 # 嵌套深度是栈的最大深度 代码 # 栈 # class Solution { public int maxDepth(String s) { Stack\u0026lt;Character\u0026gt; stack = new Stack\u0026lt;\u0026gt;(); int maxDepth = 0; for (int i = 0; i \u0026lt; s.length(); i++) { switch (s.charAt(i)) { case \u0026#39;(\u0026#39;: stack.push(\u0026#39;(\u0026#39;); maxDepth = Math.max(maxDepth, stack.size()); break; case \u0026#39;)\u0026#39;: stack.pop(); break; } } return maxDepth; } } "},{"id":230,"href":"/docs/codes/1600-to-1699/1624.-Largest-Substring-Between-Two-Equal-Characters/","title":"1624. Largest Substring Between Two Equal Characters","section":"1600 to 1699","content":" 1624. Largest Substring Between Two Equal Characters # 题目 # 给你一个字符串 s,请你返回 两个相同字符之间的最长子字符串的长度 *,*计算长度时不含这两个字符。如果不存在这样的子字符串,返回 -1 。\n子字符串 是字符串中的一个连续字符序列。\n思路 # 模拟 # 代码 # 模拟 # class Solution { public int maxLengthBetweenEqualCharacters(String s) { int[] pos = new int[26]; Arrays.fill(pos, -1); int ans = -1; for (int i = 0; i \u0026lt; s.length(); i++) { Character ch = s.charAt(i); if (pos[ch-\u0026#39;a\u0026#39;] == -1) pos[ch-\u0026#39;a\u0026#39;] = i; else ans = Math.max(ans, i-1-pos[ch-\u0026#39;a\u0026#39;]); } return ans; } } "},{"id":231,"href":"/docs/codes/1600-to-1699/1629.-Slowest-Key/","title":"1629. Slowest Key","section":"1600 to 1699","content":" 1629. Slowest Key # 题目 # LeetCode 设计了一款新式键盘,正在测试其可用性。测试人员将会点击一系列键(总计 n 个),每次一个。\n给定长度为 n 的字符串 keysPressed ,其中 keysPressed[i] 表示测试序列中第 i 个被按下的键。releaseTimes 是一个升序排列的列表,其中 releaseTimes[i] 表示松开第 i 个键的时间。字符串和数组的 下标都从 0 开始 。第 0 个键在时间为 0 时被按下,接下来每个键都 恰好 在前一个键松开时被按下。\n测试人员想要找出按键 持续时间最长 的键。第 i 次按键的持续时间为 releaseTimes[i] - releaseTimes[i - 1] ,第 0 次按键的持续时间为 releaseTimes[0] 。\n注意,测试期间,同一个键可以在不同时刻被多次按下,而每次的持续时间都可能不同。\n返回单次按键 持续时间最长 的键,如果有多个这样的键,则返回 按字母顺序排列最大 的那个键。\n思路 # 模拟 # 代码 # 模拟 # class Solution { public char slowestKey(int[] releaseTimes, String keyPressed) { char ans = keyPressed.charAt(0); int maxDuration = releaseTimes[0]; for (int i = 1; i \u0026lt; keysPressed.length(); i++) { int duration = releaseTimes[i] - releaseTimes[i-1]; if (duration == maxDuration \u0026amp;\u0026amp; keysPressed.charAt(i) \u0026gt; ans) ans = keyPressed.charAt(i); else if (duration \u0026gt; maxDuration) { ans = keyPressed.charAt(i); maxDuration = duration; } } return ans; } } "},{"id":232,"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":233,"href":"/docs/codes/1600-to-1699/1646.-Get-Maximum-in-Generated-Array/","title":"1646. Get Maximum in Generated Array","section":"1600 to 1699","content":" 1646. Get Maximum in Generated Array # 题目 # 给定一个整数n,按下述规则生成一个长度为n+1的数组nums: nums[0] = 0 num[1] = 1 当 2 \u0026lt;= 2 * i \u0026lt;= n 时,nums[2 * i] = nums[i] 当 2 \u0026lt;= 2 * i + 1 \u0026lt;= n 时,nums[2 * i + 1] = nums[i] + nums[i + 1] 返回生成数组 nums 中的最大值。 思路 # 模拟 # 打表 # 代码 # 模拟 # class Solution { public int getMaximumGenerated(int n) { if (n == 0) return 0; int[] array = new int[n + 1]; for (int i = 2; i \u0026lt;= n; i++) { if (i % 2 == 0) array[i] = array[i/2]; else array[i] = array[(i-1)/2] + array[(i-1)/2+1]; } int ans = -1; for (int num: array) ans = Math.max(ans, num); return ans; } } 致谢 # 宫水三叶\n"},{"id":234,"href":"/docs/codes/1600-to-1699/1652.-Defuse-the-Bomb/","title":"1652. Defuse the Bomb","section":"1600 to 1699","content":" 1652. Defuse the Bomb # 题目 # 你有一个炸弹需要拆除,时间紧迫!你的情报员会给你一个长度为 n 的 循环 数组 code 以及一个密钥 k 。 为了获得正确的密码,你需要替换掉每一个数字。所有数字会 同时 被替换。 如果 k \u0026gt; 0 ,将第 i 个数字用 接下来 k 个数字之和替换。 如果 k \u0026lt; 0 ,将第 i 个数字用 之前 k 个数字之和替换。 如果 k == 0 ,将第 i 个数字用 0 替换。 由于 code 是循环的, code[n-1] 下一个元素是 code[0] ,且 code[0] 前一个元素是 code[n-1] 。 给你 循环 数组 code 和整数密钥 k ,请你返回解密后的结果来拆除炸弹! 思路 # 模拟 # 前缀和 # 代码 # 模拟 # class Solution { public int[] decrypt(int[] code, int k) { int[] ans = new int[code.length]; for (int i = 0; i \u0026lt; ans.length; i++) { for (int j = 1; j \u0026lt;= Math.abs(k); j++) { int index = k \u0026gt; 0 ? (i + j) % code.length : (i - j + code.length) % code.length; ans[i] += code[index]; } } return ans; } } 致谢 # 宫水三叶\n"},{"id":235,"href":"/docs/codes/1600-to-1699/1662.-Check-If-Two-String-Arrays-are-Equivalent/","title":"1662. Check if Two String Arrays Are Equivalent","section":"1600 to 1699","content":" 1662. Check If Two String Arrays are Equivalent # 题目 # 给定两个字符串数组word1和word2。如果两个数组表示的字符串相同,返回true,否则返回false。 数组表示的字符串 是由数组中的所有元素 按顺序 连接形成的字符串。 思路 # 模拟 # 代码 # 模拟-双指针 # class Solution { public boolean arrayStringsAreEqual(String[] word1, String[] word2) { int i = 0, p = 0; int j = 0, q = 0; while (i \u0026lt; word1.length \u0026amp;\u0026amp; j \u0026lt; word2.length) { if (word1[i].charAt(p++) != word2[j].charAt(q++)) return false; if (p == word1[i].length()) { i++; p = 0; } if (q == word2[j].length()) { j++; q = 0; } } return i == word1.length \u0026amp;\u0026amp; j == word2.length; } } 模拟-API # class Solution { public boolean arrayStringsAreEqual(String[] word1, String[] word2) { String ans1 = null, ans2 = null; for (String word: word1) ans1 += word; for (String word: word2) ans2 += word; return ans1.equals(ans2); } } 致谢 # 宫水三叶\n"},{"id":236,"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":237,"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":238,"href":"/docs/codes/1600-to-1699/1672.-Richest-Customer-Wealth/","title":"1672. Richest Customer Wealth","section":"1600 to 1699","content":" 1672. Richest Customer Wealth # 题目 # 给定 m x n 的整数网格 accounts ,其中 accounts[i][j] 是第 i 位客户在第 j 家银行托管的资产数量。 客户的 资产总量 是其在各家银行托管的资产数量之和。最富有客户是 资产总量 最大的客户。 返回最富有客户所拥有的 资产总量 。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int maximumWealth(int[][] accounts) { int ans = 0; for (int[] account: accounts) { int wealth = 0; for (int val: account) wealth += val; ans = Math.max(ans, wealth); } return ans; } } "},{"id":239,"href":"/docs/codes/1600-to-1699/1684.-Count-the-Number-of-Consistent-Strings/","title":"1684. Count the Number of Consistent Strings","section":"1600 to 1699","content":" 1684. Count the Number of Consistent Strings # 题目 # 给你一个由不同字符组成的字符串 allowed 和一个字符串数组 words 。如果一个字符串的每一个字符都在 allowed 中,就称这个字符串是 一致字符串 。 请你返回 words 数组中 一致字符串 的数目。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int countConsistentStrings(String allowed, String[] words) { Set\u0026lt;Character\u0026gt; set = new HashSet\u0026lt;\u0026gt;(); for (int i = 0; i \u0026lt; sllowed.length(); i++) set.add(allowed.charAt(i)); int cnt = 0; for (String word: words) { cnt++; for (int i = 0; i \u0026lt; word.length(); i++) { if (set.contains(word.charAt(i)) == false) { cnt--; breka; } } } return cnt; } } 致谢 # 宫水三叶\n"},{"id":240,"href":"/docs/codes/1600-to-1699/1688.-Count-of-Matches-in-Tournament/","title":"1688. Count of Matches in Tournament","section":"1600 to 1699","content":" 1688. Count of Matches in Tournament # 题目 # 给你一个整数 n ,表示比赛中的队伍数。比赛遵循一种独特的赛制: 如果当前队伍数是 偶数 ,那么每支队伍都会与另一支队伍配对。总共进行 n / 2 场比赛,且产生 n / 2 支队伍进入下一轮。 如果当前队伍数为 奇数 ,那么将会随机轮空并晋级一支队伍,其余的队伍配对。总共进行 (n - 1) / 2 场比赛,且产生 (n - 1) / 2 + 1 支队伍进入下一轮。 返回在比赛中进行的配对次数,直到决出获胜队伍为止。 思路 # 模拟 # 脑筋急转弯 # 共有 n 支队伍,每场比赛淘汰一支,最终剩下一支冠军队。 即有 n−1 支队伍需要通过 n−1 场比赛被淘汰。 代码 # 模拟 # class Solution { public int numberOfMatches(int n) { int ans = 0; while (n != 1) { ans += n % 2 == 1 ? (n - 1) / 2 : n / 2; n = n % 2 == 1 ? n / 2 + 1 : n / 2; } return ans; } } 脑筋急转弯 # class Solution { public int numberOfMatches(int n) { return n-1; } } 致谢 # 宫水三叶\n"},{"id":241,"href":"/docs/codes/1600-to-1699/1694.-Reformat-Phone-Number/","title":"1694. Reformat Phone Number","section":"1600 to 1699","content":" 1694. Reformat Phone Number # 题目 # 给你一个字符串形式的电话号码 number 。number 由数字、空格 ' '、和破折号 '-' 组成。 请你按下述方式重新格式化电话号码。 首先,删除 所有的空格和破折号。 其次,将数组从左到右 每 3 个一组 分块,直到 剩下 4 个或更少数字。剩下的数字将按下述规定再分块: 2 个数字:单个含 2 个数字的块。 3 个数字:单个含 3 个数字的块。 4 个数字:两个分别含 2 个数字的块。 最后用破折号将这些块连接起来。注意,重新格式化过程中 不应该 生成仅含 1 个数字的块,并且 最多 生成两个含 2 个数字的块。 返回格式化后的电话号码。 思路 # 模拟 # 代码 # 模拟 # class Solution { public String reformatNumber(String number) { String ans = \u0026#34;\u0026#34;; String digits = \u0026#34;\u0026#34;; for (int i = 0; i \u0026lt; number.length(); i++) { Character ch = number.charAt(i); if (Character.isDigit(ch)) digits += ch; } int N = digits.length(); for (int i = 0; i \u0026lt; N; i++) { ans += digits.charAt(i); switch (N % 3) { case 0: case 2: if (i+1\u0026lt;N \u0026amp;\u0026amp; (i+1) % 3 == 0) ans += \u0026#34;-\u0026#34;; break; case 1: if (i\u0026lt;N-4 \u0026amp;\u0026amp; (i+1) % 3 == 0) ans += \u0026#34;-\u0026#34;; else if (i == N-3) ans += \u0026#34;-\u0026#34;; break; } } return ans; } } 致谢 # 宫水三叶\n"},{"id":242,"href":"/docs/codes/1700-to-1799/1700.-Number-of-Students-Unable-to-Eat-Lunch/","title":"1700. Number of Students Unable to Eat Lunch","section":"1700 to 1799","content":" 1700. Number of Students Unable to Eat Lunch # 题目 # 学校的自助午餐提供圆形和方形的三明治,分别用数字 0 和 1 表示。所有学生站在一个队列里,每个学生要么喜欢圆形的要么喜欢方形的。\n餐厅里三明治的数量与学生的数量相同。所有三明治都放在一个 栈 里,每一轮:\n如果队列最前面的学生 喜欢 栈顶的三明治,那么会 拿走它 并离开队列。 否则,这名学生会 放弃这个三明治 并回到队列的尾部。 这个过程会一直持续到队列里所有学生都不喜欢栈顶的三明治为止。 给你两个整数数组 students 和 sandwiches ,其中 sandwiches[i] 是栈里面第 i 个三明治的类型(i = 0 是栈的顶部), students[j] 是初始队列里第 j 名学生对三明治的喜好(j = 0 是队列的最开始位置)。请你返回无法吃午餐的学生数量。\n思路 # 模拟 计数 代码 # 模拟 # class Solution { public int countStudents(int[] students, int[] sandwiches) { /** 初始化三明治 */ Stack\u0026lt;Integer\u0026gt; sandwichesStack = new Stack\u0026lt;\u0026gt;(); for (int i = sandwiches.length - 1; i \u0026gt;= 0; i--) sandwichesStack.push(sandwiches[i]); /** 初始化学生队列 */ Queue\u0026lt;Integer\u0026gt; studentsQueue = new LinkedList\u0026lt;\u0026gt;(); for (int i = 0; i \u0026lt; students.length; i++) studentQueue.offer(students[i]); boolean needNewCircle = true; while (needNewCircle == true) { needNewCircle = false; for (int i = 0; i \u0026lt; studentsQueue.size(); i++) { if (studentsQueue.peek() == sandwichesStack.peek()) { studentsQeueu.poll(); sandwichesStack.pop(); needNewCircle = true; } else { studentsQueue.offer(studentsQueue.poll());/ } } } return studentsQueue.size(); } } 计数 # 致谢 # 宫水三叶\n"},{"id":243,"href":"/docs/codes/1700-to-1799/1716.-Calculate-Money-in-Leetcode-Bank/","title":"1716. Calculate Money in Leetcode Bank","section":"1700 to 1799","content":" 1716. Calculate Money in Leetcode Bank # 题目 # Hercy 想要为购买第一辆车存钱。他每天都往力扣银行里存钱。 最开始,他在周一的时候存入1块钱。从周二到周日,他每天都比前一天多存入1块钱。在接下来每一个周一,他都会比前一个周一多存入1块钱。 给定n,返回在第n天结束的时候他在力扣银行总共存了多少块钱。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int totalMoney(int n) { int N = n / 7, r = n % 7; int a1 = (1 + 7) * 7 / 2; int an = (N + N + 6) * 7 / 2; int ans = N * (a1 + an) / 2; if (r \u0026gt; 0) ans += (N + 1 + N + 1 + r - 1) * r / 2; return ans; } } "},{"id":244,"href":"/docs/codes/1700-to-1799/1720.-Decode-XORed-Array/","title":"1720. Decode Xored Array","section":"1700 to 1799","content":" 1720. Decode XORed Array # 题目 # 未知整数数组 arr 由 n 个非负整数组成。\n经编码后变为长度为 n - 1 的另一个整数数组 encoded,其中 encoded[i] = arr[i] XOR arr[i + 1]。例如 arr = [1, 0, 2, 1] 经编码后得到 encoded = [1, 2, 3]。\n给定编码后的数组 encoded 和原数组 arr 的第一个元素 first (arr[0])。\n解码返回原数组 arr,可以证明答案存在并且是唯一的。\n思路 # 代码 # class Solution { public int[] decode(int[] encoded, int first) { int[] ans = new int[encoded.length + 1]; ans[0] = first; for (int i = 1; i \u0026lt; ans.length; i++) { ans[i] = ans[i - 1] * encoded[i - 1]; } return ans; } } "},{"id":245,"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":246,"href":"/docs/codes/1700-to-1799/1725.-Number-Of-Rectangles-That-Can-Form-The-Largest-Square/","title":"1725. Number of Rectangles That Can Form the Largest Square","section":"1700 to 1799","content":" 1725. Number Of Rectangles That Can Form The Largest Square # 题目 # 给你一个数组 rectangles ,其中 rectangles[i] = [li, wi] 表示第 i 个矩形的长度为 li 、宽度为 wi 。 如果存在 k 同时满足 k \u0026lt;= li 和 k \u0026lt;= wi ,就可以将第 i 个矩形切成边长为 k 的正方形。例如,矩形 [4,6] 可以切成边长最大为 4 的正方形。 设 maxLen 为可以从矩形数组 rectangles 切分得到的 最大正方形 的边长。 请你统计有多少个矩形能够切出边长为 maxLen 的正方形,并返回矩形 数目 。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int countGoodRectangles(int[][] rectangles) { int maxLen = 0, ans = 0; for (int[] rectangle: rectangles) { int width = Math.min(rectangle[0], rectangle[1]); if (maxLen == width) ans++; else if (maxLen \u0026lt; width) { maxLen = width; ans = 1; } } return ans; } } "},{"id":247,"href":"/docs/codes/1700-to-1799/1732.-Find-the-Highest-Altitude/","title":"1732. Find the Highest Altitude","section":"1700 to 1799","content":" 1732. Find the Highest Altitude # 题目 # 有一个自行车手打算进行一场公路骑行,这条路线总共由 n + 1 个不同海拔的点组成。自行车手从海拔为 0 的点 0 开始骑行。 给你一个长度为 n 的整数数组 gain ,其中 gain[i] 是点 i 和点 i + 1 的 净海拔高度差(0 \u0026lt;= i \u0026lt; n)。请你返回 最高点的海拔 。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int largestAltitude(int[] gain) { int altitude = 0, maximum = 0; for (int diff: gain) { altitude += diff; maximum = Math.max(maximum, altitude); } return maximum; } } "},{"id":248,"href":"/docs/codes/1700-to-1799/1736.-Latest-Time-by-Replacing-Hidden-Digits/","title":"1736. Latest Time by Replacing Hidden Digits","section":"1700 to 1799","content":" 1736. Latest Time by Replacing Hidden Digits # 题目 # 给你一个字符串 time ,格式为 hh:mm(小时:分钟),其中某几位数字被隐藏(用 ? 表示)。 有效的时间为 00:00 到 23:59 之间的所有时间,包括 00:00 和 23:59 。 替换 time 中隐藏的数字,返回你可以得到的最晚有效时间。 思路 # 模拟 # 代码 # 模拟 # class Solution { public String maximumTime(String time) { char[] ans = time.toCharArray(); if (ans[0] == \u0026#39;?\u0026#39;) ans[0] = ans[1] == \u0026#39;?\u0026#39; || ans[1] \u0026lt; \u0026#39;4\u0026#39; ? \u0026#39;2\u0026#39; : \u0026#39;1\u0026#39;; if (ans[1] == \u0026#39;?\u0026#39;) ans[1] = ans[0] == \u0026#39;2\u0026#39; ? \u0026#39;3\u0026#39; : \u0026#39;9\u0026#39;; if (ans[3] == \u0026#39;?\u0026#39;) ans[3] = \u0026#39;5\u0026#39;; if (ans[4] == \u0026#39;?\u0026#39;) ans[4] = \u0026#39;9\u0026#39;; return String.valueOf(ans); } } 致谢 # 宫水三叶\n"},{"id":249,"href":"/docs/codes/1700-to-1799/1748.-Sum-of-Unique-Elements/","title":"1748. Sum of Unique Elements","section":"1700 to 1799","content":" 1748. Sum of Unique Elements # 题目 # 给定整数数组 nums,数组中唯一元素是那些只出现 恰好一次 的元素。 返回 nums 中唯一元素的 和。 1 \u0026lt;= nums[i] \u0026lt;= 100 思路 # 哈希 # 代码 # 哈希 # class Solution { public int sumOfUnique(int[] nums) { Map\u0026lt;Integer, Integer\u0026gt; map = new HashMap\u0026lt;\u0026gt;(); for (int num: nums) { if (map.containsKey(num) == false) map.put(num, 1); else map.put(num, map.get(num) + 1); } int ans = 0; for (int num: nums) { if (map.get(num) == 1) ans += num; } return ans; } } 致谢 # 宫水三叶\n"},{"id":250,"href":"/docs/codes/1700-to-1799/1768.-Merge-Strings-Alternatively/","title":"1768. Merge Strings Alternatively","section":"1700 to 1799","content":" 1768. Merge Strings Alternatively # 题目 # 给你两个字符串 word1 和 word2 。请你从 word1 开始,通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长,就将多出来的字母追加到合并后字符串的末尾。 返回 合并后的字符串 。 思路 # 模拟 # 代码 # 模拟 # class Solution { public String mergeAlternatively(String word1, String word2) { char[] arr = new char[word1.length() + word2.length()]; int ptr1 = 0, ptr2 = 0, ptr = 0; while (ptr \u0026lt; arr.length) { if (ptr1 == word1.length()) arr[ptr++] = word2.charAt(ptr2++); else if (ptr2 == word2.length()) arr[ptr++] = word1.charAt(ptr1++); else { arr[ptr++] = word1.charAt(ptr1++); arr[ptr++] = word2.charAt(ptr2++); } } return String.valueOf(arr); } } 致谢 # 宫水三叶\n"},{"id":251,"href":"/docs/codes/1700-to-1799/1773.-Count-Items-Matching-a-Rule/","title":"1773. Count Items Matching a Rule","section":"1700 to 1799","content":" 1773. Count Items Mathcing a Rule # 题目 # 给你一个数组 items ,其中 items[i] = [typei, colori, namei] ,描述第 i 件物品的类型、颜色以及名称。 另给你一条由两个字符串 ruleKey 和 ruleValue 表示的检索规则。 如果第 i 件物品能满足下述条件之一,则认为该物品与给定的检索规则 匹配 : ruleKey == \u0026quot;type\u0026quot; 且 ruleValue == typei 。 ruleKey == \u0026quot;color\u0026quot; 且 ruleValue == colori 。 ruleKey == \u0026quot;name\u0026quot; 且 ruleValue == namei 。 统计并返回 匹配检索规则的物品数量 。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int countMatches(List\u0026lt;List\u0026lt;String\u0026gt;\u0026gt; items, String ruleKey, String ruleValue) { int count = 0; for (List\u0026lt;String\u0026gt; item: items) { switch (ruleKey) { case \u0026#34;type\u0026#34; : if (item.get(0).equals(ruleValue)) count += 1; break; case \u0026#34;color\u0026#34; : if (item.get(1).equals(ruleValue)) count += 1; break; case \u0026#34;name\u0026#34; : if (item.get(2).equals(ruleValue)) count += 1; break; } } return count; } } 致谢 # 宫水三叶\n"},{"id":252,"href":"/docs/codes/1700-to-1799/1790.-Check-if-One-String-Swap-Can-Make-Strings-Equal/","title":"1790. Check if One String Swap Can Make Strings Equal","section":"1700 to 1799","content":" 1790. Check if One String Swap Can Make Strings Equal # 题目 # 给定长度相等的两个字符串 s1 和 s2。 一次字符串交换操作的步骤为:选出某个字符串中的两个下标,并交换这两个下标对应的字符。 如果对其中一个字符串执行最多一次字符串交换就可以使两个字符串相等,返回true;否则返回false 思路 # 模拟 # 代码 # 模拟 # class Solution { public boolean areAlmostEqual(String s1, String s2) { if (s1.length() != s2.length()) return false; int left = -1, right = -1; for (int i = 0; i \u0026lt; s1.length(); i++) { if (s1.charAt(i) != s2.charAt(i)) { if (left == -1) left = i; else if (right == -1) right = i; else return false; } } if (left == -1) return true; if (right == -1) return false; return s1.charAt(left) == s2.charAt(right) \u0026amp;\u0026amp; s1.charAt(right) == s2.charAt(left); } } 计数 # 致谢 # 宫水三叶\n"},{"id":253,"href":"/docs/codes/1700-to-1799/1791.-Find-Center-of-Star-Graph/","title":"1791. Find Center of Star Graph","section":"1700 to 1799","content":" 1791. Find Center of Star Graph # 题目 # 有一个无向的 星型 图,由 n 个编号从 1 到 n 的节点组成。星型图有一个 中心 节点,并且恰有 n - 1 条边将中心节点与其他每个节点连接起来。 给你一个二维整数数组 edges ,其中 edges[i] = [ui, vi] 表示在节点 ui 和 vi 之间存在一条边。请你找出并返回 edges 所表示星型图的中心节点。 思路 # 模拟 # 欧拉回路 # 代码 # 模拟 # class Solution { public int findCenter(int[][] edges) { int[] edge1 = edges[0], edge2 = edges[1]; if (edge2[0] == edge1[0] || edge2[0] == edge1[1]) return edge2[0]; return edge2[1]; } } 欧拉回路 # 致谢 # 宫水三叶\n"},{"id":254,"href":"/docs/codes/1800-to-1899/1816.-Truncate-Sentence/","title":"1816. Truncate Sentence","section":"1800 to 1899","content":" 1816. Truncate Sentence # 题目 # 句子 是一个单词列表,列表中的单词之间用单个空格隔开,且不存在前导或尾随空格。每个单词仅由大小写英文字母组成(不含标点符号)。 例如,\u0026quot;Hello World\u0026quot;、\u0026quot;HELLO\u0026quot; 和 \u0026quot;hello world hello world\u0026quot; 都是句子。 给你一个句子 s 和一个整数 k ,请你将 s 截断 ,使截断后的句子仅含 前 k 个单词。返回 截断 s** 后得到的句子*。 思路 # 模拟 # 代码 # 模拟 # class Solution { public String truncateSentence (String s, int k) { char[] charArray = s.toCharArray(); String ans = \u0026#34;\u0026#34;; for (int i = 0, cnt = 0; i \u0026lt; charArray.length \u0026amp;\u0026amp; cnt \u0026lt; k; i++) { if (charArray[i] == \u0026#39; \u0026#39; \u0026amp;\u0026amp; ++cnt == k) return ans; ans += String.valueOf(charArray[i]); } return ans; } } "},{"id":255,"href":"/docs/codes/1800-to-1899/1822.-Sign-of-the-Product-of-an-Array/","title":"1822. Sign of the Product of an Array","section":"1800 to 1899","content":" 1822. Sign of the Product of an Array # 题目 # 给定整数数组 nums,令product为数组nums中所有元素值的乘积。 返回乘积的符号。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int arraySign(int[] nums) { int ans = 1; for (int num: nums) { if (num == 0) return 0; else if (num \u0026lt; 0) ans *= -1; } return ans; } } 致谢 # 宫水三叶\n"},{"id":256,"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":257,"href":"/docs/codes/1900-to-1999/1991.-Find-the-Middle-Index-in-Array/","title":"1991. Find the Middle Index in Array","section":"1900 to 1999","content":" 1999. Find the Middle Index in Array # 题目 # 给定下标从 0 开始的整数数组 nums ,请你找到 最左边 的中间位置 middleIndex (即所有可能中间位置下标最小的一个)。 中间位置 middleIndex 是满足 nums[0] + nums[1] + ... + nums[middleIndex-1] == nums[middleIndex+1] + nums[middleIndex+2] + ... + nums[nums.length-1] 的数组下标。 如果 middleIndex == 0 ,左边部分的和定义为 0 。类似的,如果 middleIndex == nums.length - 1 ,右边部分的和定义为 0 。 返回满足上述条件 最左边 的 middleIndex ,若不存在这样的中间位置,返回 -1 。 思路 # 前缀和 # 代码 # 前缀和 # class Solution { public int findMiddleIndex(int[] nums) { int total = 0; for(int num: nums) total += num; int prefix = 0; for (int i = 0; i \u0026lt; nums.length; i++) { if (prefix == total - prefix - nums[i]) return i; prefix += nums[i]; } return -1; } } "},{"id":258,"href":"/docs/codes/2000-to-2099/2000.-Reverse-Prefix-of-Word/","title":"2000. Reverse Prefix of Word","section":"2000 to 2099","content":" 2000. Reverse Prefix of Word # 题目 # 给定下标从 0 开始的字符串 word 和一个字符 ch。 找出 ch 第一次出现的下标 i,反转 word 中从下标 0 开始、直到下标 i 结束的字符段。 若 word 中不存在字符 ch,无需进行任何操作。 思路 # 模拟 # 代码 # 模拟 # class Solution { public String reversePrefix(String word, char ch) { int ptr = 0; while (ptr \u0026lt; word.length() \u0026amp;\u0026amp; word.charAt(ptr) != ch) ptr++; if (ptr == word.length()) return word; char[] charArray = word.toCharArray(); for (int i = 0, j = ptr; i \u0026lt; j; i++, j--) { Character temp = charArray[i]; charArray[i] = charArray[j]; charArray[j] = temp; } return String.valueOf(charArray); } } "},{"id":259,"href":"/docs/codes/2000-to-2099/2006.-Count-Number-of-Pairs-With-Absolute-Difference-K/","title":"2006. Count Number of Pairs With Absolute Difference K","section":"2000 to 2099","content":" 2000. Reverse Prefix of Word # 题目 # 给定整数数组 nums 和一个整数 k。 返回数对 (i, j) 的数目,满足 i \u0026lt; j 且 |nums[i] - nums[j]| == k。 1 \u0026lt;= nums[i] \u0026lt;= 100 1 \u0026lt;= k \u0026lt;= 99 思路 # 哈希 # 代码 # 哈希 # class Solution { public int countKDifference(int[] nums, int k) { Map\u0026lt;Integer, Integer\u0026gt; map = new HashMap\u0026lt;\u0026gt;(); int ans = 0; for (int num: nums) { ans += map.getOrDefault(num - k, 0); ans += map.getOrDefault(num + k, 0); map.put(num, map.getOrDefault(num, 0) + 1); } return ans; } } 致谢 # 宫水三叶\n"},{"id":260,"href":"/docs/codes/2000-to-2099/2016.-Maximum-Difference-Between-Increasing-Elements/","title":"2016. Maximum Difference Between Increasing Elements","section":"2000 to 2099","content":" 2016. Maximum Difference Between Increasing Elements # 题目 # 给定下标从 0 开始的整数数组 nums,该数组的大小为 n。 计算 nums[j] - nums[i] 能求得的最大差值,其中 0 \u0026lt;= i \u0026lt; j \u0026lt; n 且 nums[i] \u0026lt; nums[j]。 返回 最大差值。如果不存在满足要求的 i 和 j,返回 -1。 思路 # 模拟 # 类似 买卖股票的最佳时机 代码 # 模拟 # class Solution { public int maximumDifference(int[] nums) { int ans = -1, maxVal = nums[0]; for (int num: nums) { minVal = Math.min(minVal, num); ans = Math.max(ans, num - minVal); } return ans \u0026gt; 0 ? ans : -1; } } "},{"id":261,"href":"/docs/codes/2000-to-2099/2022.-Convert-1D-Array-into-2D-Array/","title":"2022. Convert 1 D Array Into 2 D Array","section":"2000 to 2099","content":" 2022. Convert 1D Array into 2D Array # 题目 # 给定下标从 0 开始的一维整数数组 original 和两个整数 m 和 n。 使用original中所有元素创建一个m行n列的二维数组。 根据上述过程返回一个 m x n 的二维数组。如果无法构成这样的二维数组,返回一个空的二维数组。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int[][] construct2DArray(int[] original, int m, int n) { if (original.length != m * n) return new int[0][0]; int[][] ans = new int[m][n]; for (int i = 0; i \u0026lt; original.length; i++0) { int row = i / n, col = i % n; ans[row][col] = original[i]; } return ans; } } "},{"id":262,"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":263,"href":"/docs/codes/2000-to-2099/2047.-Number-of-Valid-Words-in-a-Sentence/","title":"2047. Number of Valid Words in a Sentence","section":"2000 to 2099","content":" 2047. Number of Valid Words in a Sentence # 题目 # 句子仅由小写字母('a' 到 'z')、数字('0' 到 '9')、连字符('-')、标点符号('!'、'.' 和 ',')以及空格(' ')组成。每个句子可以根据空格分解成 一个或者多个 token ,这些 token 之间由一个或者多个空格 ' ' 分隔。 如果一个 token 同时满足下述条件,则认为这个 token 是一个有效单词: 仅由小写字母、连字符和/或标点(不含数字)组成。 至多一个 连字符 '-' 。如果存在,连字符两侧应当都存在小写字母(\u0026quot;a-b\u0026quot; 是一个有效单词,但 \u0026quot;-ab\u0026quot; 和 \u0026quot;ab-\u0026quot; 不是有效单词)。 至多一个 标点符号。如果存在,标点符号应当位于 token 的 末尾 。 这里给出几个有效单词的例子:\u0026quot;a-b.\u0026quot;、\u0026quot;afad\u0026quot;、\u0026quot;ba-c\u0026quot;、\u0026quot;a!\u0026quot; 和 \u0026quot;!\u0026quot; 。 给你一个字符串 sentence ,请你找出并返回 sentence 中 有效单词的数目 。 思路 # 模拟 # 代码 # 模拟 # class Solution { public boolean isValid(String token) { if (token.length() == 0) return false; char[] array = token.toCharArray(); int N = array.length; /** rule 2 */ int numHypen = 0; for (int i = 0; i \u0026lt; N; i++) { Character ch = array[i]; /** rule 1 */ if (Character.isDigit(ch)) return false; /** rule 2 */ if (ch == \u0026#39;-\u0026#39;) { if (i == 0 || i == N - 1) return false; if (++numHypen \u0026gt; 1) return false; if (Character.isLetter(array[i+1]) == false) return false; } /** rule 3 */ if (ch == \u0026#39;.\u0026#39; || ch == \u0026#39;,\u0026#39; || ch == \u0026#39;!\u0026#39;) return i == N - 1; } return true; } public int countValidWords(String sentence) { String[] tokens = sentence.split(\u0026#34; \u0026#34;); int validWords = 0; for (String token: tokens) { if (isValid(token) == true) validWords++; } return validWords; } } "},{"id":264,"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":265,"href":"/docs/codes/2000-to-2099/2073.-Time-Needed-to-Buy-Tickets/","title":"2073. Time Needed to Buy Tickets","section":"2000 to 2099","content":" 2073. Time Needed to Buy Tickets # 题目 # 有 n 个人前来排队买票,其中第 0 人站在队伍 最前方,第 (n - 1) 人站在队伍 最后方。\n给定下标从 0 开始的整数数组 tickets,数组长度为 n,其中第 i 人想要购买的票数为 tickets[i]。\n每个人买票都需要用掉 恰好 1 秒。一个人 一次只能买一张票,如果需要购买更多票,他必须走到 队尾 重新排队(瞬间 发生,不计时间)。如果一个人没有剩下需要的票,那他将会 离开 队伍。\n返回位于位置 k(下标从 0 开始)的人完成买票需要的时间。\n思路 # 代码 # class Solution { public int timeRequiredToBuy(int[] tickets, int k) { int ans = 0; for (int i = 0; i \u0026lt; k; i++) ans += Math.min(tickets[i], tickets[k]); ans += tickets[k]; for (int i = k + 1; i \u0026lt; tickets.length; i++) ans += Math.min(tickets[i], tickets[k] - 1); return ans; } } "},{"id":266,"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":267,"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":268,"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":269,"href":"/docs/codes/2100-to-2199/2169.-Count-Operations-to-Obtain-Zero/","title":"2169. Count Operations to Obtain Zero","section":"2100 to 2199","content":" 2169. Count Operations to Obtain Zero # 题目 # 给你两个 非负 整数 num1 和 num2。\n每一步 操作 中,如果 num1 \u0026gt;= num2 ,你必须用 num1 减 num2 ;否则,你必须用 num2 减 num1 。\n返回使 num1 = 0 或 num2 = 0 的 操作数 。\n思路 # 模拟 代码 # class Solution { public int countOperations(int num1, int num2) { int step = 0; while (num != 0 \u0026amp;\u0026amp; num2 != 0) { if (num1 \u0026gt;= num2) num1 -= num2; else num2 -= num1; step += 1; } return step; } } "},{"id":270,"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":271,"href":"/docs/codes/2200-to-2299/2220.-Minimum-Bit-Flips-to-Convert-Number/","title":"2220. Minimum Bit Flips to Convert Number","section":"2200 to 2299","content":" 2220. Minimum Bit Flips to Convert Number # 题目 # 一次 位翻转 定义为将数字 x 二进制位中的一个位进行 翻转 操作,即将 0 变成 1,或者将 1 变成 0。\n给定两个整数 start 和 goal,返回将 start 转变为 goal 的 最少位翻转 次数。\n思路 # 代码 # class Solution { public int minBitFlips(int start, int goal) { int xor = start ^ goal; int hammingDistance = 0; for (int i = 31; i \u0026gt;= 0; i--) { if (((xor \u0026gt;\u0026gt; i) \u0026amp; 1) == 1) hammingDistance += 1; } return hammingDistance; } } "},{"id":272,"href":"/docs/codes/2200-to-2299/2235.-Add-Two-Integers/","title":"2235. Add Two Integers","section":"2200 to 2299","content":" 2235. Add Two Integers # 题目 # 给定两个整数 num1 和 num2,返回这两个整数的和。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int sum(int num1, int num2) { return num1 + num2; } } "},{"id":273,"href":"/docs/codes/2200-to-2299/2236.-Root-Equals-Sum-of-Children/","title":"2236. Root Equals Sum of Children","section":"2200 to 2299","content":" 2236. Root Equals Sum of Children # 题目 # 给定二叉树的根节点 root,该二叉树恰由三个节点组成:根节点、左子节点、右子节点。\n如果根节点值等于两个子节点值值和,返回 true,否则返回 false。\n思路 # 代码 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public boolean checkTree(TreeNode root) { return root.val == root.left.val + root.right.val; } } "},{"id":274,"href":"/docs/codes/2200-to-2299/2289.-Steps-to-Make-Array-Non-decreasing/","title":"2289. Steps to Make Array Non Decreasing","section":"2200 to 2299","content":" 2289. Steps to Make Array Non-decreasing # 题目 # 给定一个下标从 0 开始的整数数组 nums。在一步操作中,移除所有满足 nums[i-1] \u0026gt; nums[i] 的 nums[i],其中 0 \u0026lt; i \u0026lt; nums.length。\n重复执行步骤,直到 nums 变为 非递减 数组,返回所需执行的操作数。\n思路 # 代码 # class Solution { /** 观察: 如果一个结点的左侧结点未发生变化,则该结点在本轮不会被删除 * 推论: 仅有被删除的结点会触发下一轮删除。当某结点被删除时,考虑是否将被删除结点的下一个结点纳入下一轮删除的列表里 */ private class ListNode { public int val; public ListNode prev; public ListNode next; ListNode(int val, ListNode prev, ListNode next) { this.val = val; this.prev = prev; this.next = next; } } public int totalSteps(int[] nums) { ListNode sentinel = new ListNode(-1, null, null); sentinel.prev = sentinel.next = sentinel; /** 逆序遍历数组,将其转化为双向链表 * 若数组的某个元素满足删除条件,则将相应的结点记录在队列中 */ Queue\u0026lt;ListNode\u0026gt; deletePoints = new LinkedList\u0026lt;\u0026gt;(); for (int i=nums.length - 1; i \u0026gt;= 0; i--) { sentinel.next = new ListNode(nums[i], sentinel, sentinel.next); sentinel.next.next.prev = sentinel.next; if (i \u0026gt;= 1 \u0026amp;\u0026amp; nums[i] \u0026lt; nums[i-1]) deletePoints.offer(sentinel.next); } /** 对需要执行的操作数进行计数 */ int step = 0; while (deletePoints.size() != 0) { step += 1; Queue\u0026lt;ListNode\u0026gt; newDeletePoints = new LinkedList\u0026lt;\u0026gt;(); for (ListNode node: deletePoints) { if (node.next != sentinel \u0026amp;\u0026amp; node.next.val \u0026lt; node.prev.val) { /** 避免某待删除结点被重复添加 */ if (newDeletePoints.peek() != node.next) newDeletePoints.offer(node.next); } node.prev.next = node.next; node.next.prev = node.prev; } deletePoints = newDeletePoints; } return step; } } "},{"id":275,"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":276,"href":"/docs/codes/2300-to-2399/2319.-Check-if-Matrix-is-X-Matrix/","title":"2319. Check if Matrix Is X Matrix","section":"2300 to 2399","content":" 2319. Check if Matrix Is X-Matrix # 题目 # X 矩阵 是满足下列条件的方阵 矩阵对角线上所有元素都 非零 非对角线元素均 为零 给定 n 阶方阵 grid,判断 grid 是否为 X 矩阵 思路 # 模拟 # 代码 # 模拟 # class Solution { public boolean checkXMatrix(int[][] grid) { boolean valid = true; for (int i = 0; i \u0026lt; grid.length; i++) { for (int j = 0; j \u0026lt; grid.length; j++) { if (i == j) valid \u0026amp;= grid[i][j] != 0; else if (j == grid.length - 1 - i) valid \u0026amp;= grid[i][j] != 0; else valid \u0026amp;= grid[i][j] == 0; } } return valid; } } "},{"id":277,"href":"/docs/codes/2300-to-2399/2325.-Decode-the-Message/","title":"2325. Decode the Message","section":"2300 to 2399","content":" 2325. Decode the Message # 题目 # 给定字符串 key 和 message ,分别表示 密钥 和 密文。解密步骤如下:\n使用 key 中 26 个英文小写字母第一次出现的顺序作为替换表中的字母 顺序 。 将替换表与普通英文字母表对齐,形成 对照表。 按照对照表 替换 message 中的每个字母。 空格 ' ' 保持不变。 例如,key = \u0026quot;happy boy\u0026quot;(实际的加密密钥会包含字母表中每个字母 至少一次),得到部分对照表('h' -\u0026gt; 'a'、'a' -\u0026gt; 'b'、'p' -\u0026gt; 'c'、'y' -\u0026gt; 'd'、'b' -\u0026gt; 'e'、'o' -\u0026gt; 'f')。\n返回解密后的消息。\n思路 # 哈希 # 代码 # 哈希 # class Solution { public String decodeMessage(String key, String message) { Map\u0026lt;Character, Character\u0026gt; map = new HashMap\u0026lt;\u0026gt;(); char charPoint = \u0026#39;a\u0026#39;; for (int i = 0; i \u0026lt; key.length(); i++) { char ch = key.charAt(i); if (ch != \u0026#39; \u0026#39; \u0026amp;\u0026amp; map.containsKey(ch) == false) map.put(ch, charPoint++); } char[] messageArray = message.toCharArray(); for (int i = 0; i \u0026lt; messageArray.length; i++) { if (messageArray[i] != \u0026#39; \u0026#39;) messageArray[i] = map.get(messageArray[i]); } return String.valueOf(messageArray); } } "},{"id":278,"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":279,"href":"/docs/codes/2300-to-2399/2331.-Evaluate-Boolean-Binary-Tree/","title":"2331. Evaluate Boolean Binary Tree","section":"2300 to 2399","content":" 2331. Evaluate Boolean Binary Tree # 题目 # 给定一棵 完整二叉树 的根,这棵树有以下特征:\n叶子节点 要么值为 0 要么值为 1,其中 0 表示 false,1 表示 true。 非叶子节点 要么值为 2 要么值为 3,其中 2 表示逻辑或 OR,3表示逻辑与 AND。 计算一个节点的值方式如下:\n如果节点是个叶子节点,那么节点的 值 为它本身,即 true 或 false。 否则,计算 两个孩子的节点值,然后将该节点的运算符对两个孩子值进行 运算。 返回根节点 root 的不二运算值。\n完整二叉树 是每个节点有 0 个或者 2 个孩子的二叉树。\n思路 # 代码 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { public boolean evaluateTree(TreeNode root) { boolean ans = true; switch (root.val) { case 0: ans = false; break; case 1: ans = true; break; case 2: ans = evaluateTree(root.left) | evaluateTree(root.right); break; case 3: ans = evaluateTree(root.left) \u0026amp; evaluateTree(root.right); break; } return ans; } } "},{"id":280,"href":"/docs/codes/2400-to-2499/2460.-Apply-Operations-to-an-Array/","title":"2460. Apply Operations to an Array","section":"2400 to 2499","content":" 2460. Apply Operations to an Array # 题目 # 给你一个下标从 0 开始的数组 nums ,数组大小为 n ,且由 非负 整数组成。 对数组执行 n - 1 步操作,其中第 i 步操作(从 0 开始计数)要求对 nums 中第 i 个元素执行下述指令: 如果 nums[i] == nums[i + 1] ,则 nums[i] 的值变成原来的 2 倍,nums[i + 1] 的值变成 0 。否则,跳过这步操作。 在执行完 全部 操作后,将所有 0 移动 到数组的 末尾 。 例如,数组 [1,0,2,0,0,1] 将所有 0 移动到末尾后变为 [1,2,1,0,0,0] 。 返回结果数组。 注意 操作应当 依次有序 执行,而不是一次性全部执行。 思路 # 模拟 # 代码 # 模拟 # class Solution { public int[] moveZeros(int[] nums) { int left = 0, right = 0; while (right \u0026lt; nums.length) { if (nums[right] != 0) { nums[left++] = nums[right]; right += 1; } } while (left \u0026lt; nums.length) nums[left++] = 0; return nums; } public int[] applyOperations(int[] nums) { for (int i = 0; i \u0026lt; nums.length - 1; i++) { if (nums[i] == nums[i+1]) { nums[i] *= 2; nums[i+1] = 0; } } return moveZeros(nums); } } 致谢 # 灵茶山艾府\n"},{"id":281,"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":282,"href":"/docs/codes/LCP/50.-%E5%AE%9D%E7%9F%B3%E8%A1%A5%E7%BB%99/","title":"50. 宝石补给","section":"Lcp","content":" LCP 50. 宝石补给 # 题目 # 欢迎各位勇者来到力扣新手村,在开始试炼之前,请各位勇者先进行「宝石补给」。\n每位勇者初始都拥有一些能量宝石, gem[i] 表示第 i 位勇者的宝石数量。现在这些勇者们进行了一系列的赠送,operations[j] = [x, y] 表示在第 j 次的赠送中 第 x 位勇者将自己一半的宝石(需向下取整)赠送给第 y 位勇者。\n在完成所有的赠送后,请找到拥有最多宝石的勇者和拥有最少宝石的勇者,并返回他们二者的宝石数量之差。\n思路 # 模拟 代码 # class Solution { public int giveGem(int[] gem, int[][] operations) { for (int i = 0; i \u0026lt; operations.length; i++) { int giver = operations[i][0], claimant = operations[i][1]; int numGems = gem[giver] / 2; gem[giver] -= numGems; gem[claimant] += numGems; } int minGems = gem[0], maxGems = gem[0]; for (int i = 0; i \u0026lt; gem.length; i++) { minGems = Math.min(minGems, gem[i]); maxGems = Math.max(maxGems, gem[i]); } return maxGems - minGems; } } "},{"id":283,"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":284,"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":285,"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":286,"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":287,"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":288,"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":289,"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":290,"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":291,"href":"/docs/codes/%E5%89%91%E6%8C%87-Offer-2/002.-%E4%BA%8C%E8%BF%9B%E5%88%B6%E5%8A%A0%E6%B3%95/","title":"002. 二进制加法","section":"剑指 Offer 2","content":" 剑指 Offer II 002. 二进制加法 # 题目 # 给定两个01字符串a和b,计算它们的和,并以二进制字符串的形式输出。 输入为非空字符串且只包含数字1和0。 思路 # 模拟 # 代码 # 模拟 # class Solution { public String addBinary(String a, String b) { String longer = a.length() \u0026gt; b.length() ? a : b, shorter = a.length() \u0026gt; b.length() ? b : a; int ptrLonger = longer.length() - 1, ptrShorter = shorter.length() - 1; char[] ans = longer.toCharArray(); int sum = 0, carry = 0; while (ptrShorter \u0026gt;= 0) { sum = longer.charAt(ptrLonger) - \u0026#39;0\u0026#39; + shorter.charAt(ptrShorter) - \u0026#39;0\u0026#39; + carry; ans[ptrLonger] = sum % 2 \u0026gt; 0 ? \u0026#39;1\u0026#39; : \u0026#39;0\u0026#39;; carry = sum \u0026gt; 1 ? 1 : 0; ptrLonger--; ptrShorter--; } while (carry \u0026gt; 0) { if (ptrLonger == -1) return \u0026#34;1\u0026#34; + String.valueOf(ans); sum = ans[ptrLonger] - \u0026#39;0\u0026#39; + carry; ans[ptrLonger--] = sum % 2 \u0026gt; 0 ? \u0026#39;1\u0026#39; : \u0026#39;0\u0026#39;; carry = sum \u0026gt; 1 ? 1 : 0; } return String.valueOf(ans); } } 致谢 # 负雪明烛\n"},{"id":292,"href":"/docs/codes/%E5%89%91%E6%8C%87-Offer-2/041.-%E6%BB%91%E5%8A%A8%E7%AA%97%E5%8F%A3%E7%9A%84%E5%B9%B3%E5%9D%87%E5%80%BC/","title":"041. 滑动窗口的平均值","section":"剑指 Offer 2","content":" 剑指 Offer II 041. 滑动窗口的平均值 # 题目 # 给定一个整数数据流和一个窗口大小,根据该滑动窗口的大小,计算滑动窗口里所有数字的平均值。 实现 MovingAverage 类: MovingAverage(int size) 用窗口大小 size 初始化对象。 double next(int val) 成员函数 next 每次调用的时候都会往滑动窗口增加一个整数,请计算并返回数据流中最后 size 个值的移动平均值,即滑动窗口里所有数字的平均值。 思路 # 队列 # 代码 # 队列 # class MovingAverage { private Queue\u0026lt;Integer\u0026gt; queue; private int capacity; private int sum; public MovingAverage(int size) { this.queue = new LinkedList\u0026lt;\u0026gt;(); this.capacity = size; this.sum = 0; } public double next(int val) { if (this.queue.size() == this.capacity) this.sum -= this.queue.poll(); this.queue.offer(val); this.sum += val; return (double) this.sum / this.queue.size(); } } "},{"id":293,"href":"/docs/codes/%E5%89%91%E6%8C%87-Offer-2/042.-%E6%9C%80%E8%BF%91%E8%AF%B7%E6%B1%82%E6%AC%A1%E6%95%B0/","title":"042. 最近请求次数","section":"剑指 Offer 2","content":" 剑指 Offer II 042. 最近请求次数 # 题目 # 写一个 RecentCounter 类来计算特定时间范围内最近的请求。 请你实现 RecentCounter 类: RecentCounter() 初始化计数器,请求数为 0 。 int ping(int t) 在时间 t 添加一个新请求,其中 t 表示以毫秒为单位的某个时间,并返回过去 3000 毫秒内发生的所有请求数(包括新请求)。确切地说,返回在 [t-3000, t] 内发生的请求数。 每次对 ping 的调用都使用比之前更大的 t 值。 思路 # 队列 # 代码 # 队列 # class RecentCounter { private Queue\u0026lt;Integer\u0026gt; queue; public RecentCounter() { this.queue = new LinkedList\u0026lt;\u0026gt;(); } public int ping(int t) { queue.offer(t); while(queue.peek() \u0026lt; t - 3000) queue.poll(); return queue.size(); } } "},{"id":294,"href":"/docs/codes/%E5%89%91%E6%8C%87-Offer-2/058.-%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/","title":"058. 左旋转字符串","section":"剑指 Offer 2","content":" 剑指 Offer II 058. 左旋转字符串 # 题目 # 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。 请定义一个函数实现字符串左旋转操作的功能。 比如,输入字符串\u0026quot;abcdefg\u0026quot;和数字2,该函数将返回左旋转两位得到的结果\u0026quot;cdefgab\u0026quot;。 思路 # 三次翻转 # 代码 # 三次翻转 # class Solution { public void swap(char[] charArray, int i, int j) { char temp = charArray[i]; charArray[i] = charArray[j]; charArray[j] = temp; } public String reverseLeftWords(String s, int n) { char[] charArray = s.toCharArray(); for (int i = 0, j = charArray.length - 1; i \u0026lt; j; i++, j--) swap(charArray, i, j); for (int i = 0, j = charArray.length - n - 1; i \u0026lt; j; i++, j--) swap(charArray, i, j); for (int i = charArray.length - n, j = charArray.length - 1; i \u0026lt; j; i++, j--) swap(charArray, i, j); return String.valueOf(charArray); } } "},{"id":295,"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":296,"href":"/docs/codes/%E5%89%91%E6%8C%87-Offer/09.-%E7%94%A8%E4%B8%A4%E4%B8%AA%E6%A0%88%E5%AE%9E%E7%8E%B0%E9%98%9F%E5%88%97/","title":"09. 用两个栈实现队列","section":"剑指 Offer","content":" 剑指 Offer 09. 用两个栈实现队列 # 题目 # 用两个栈实现一个队列。 队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。 (若队列中没有元素,deleteHead 操作返回 -1 ) 思路 # 代码 # class CQueue { Stack\u0026lt;Integer\u0026gt; inStack, outStack; public CQueue() { this.inStack = new Stack\u0026lt;\u0026gt;(); this.outStack = new Stack\u0026lt;\u0026gt;(); } public void appendTail(int value) { this.inStack.push(value); } public int deleteHead() { if (this.outStack.size() == 0 \u0026amp;\u0026amp; this.inStack.size() == 0) return -1; if (this.outStack.size() == 0) { while (this.inStack.size() != 0) { this.outStack.push(this.inStack.pop()); } } return this.outStack.pop(); } } /** * Your CQueue object will be instantiated and called as such: * CQueue obj = new CQueue(); * obj.appendTail(value); * int param_2 = obj.deleteHead(); */ "},{"id":297,"href":"/docs/codes/%E5%89%91%E6%8C%87-Offer/10.-%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97/","title":"10. 斐波那契数列","section":"剑指 Offer","content":" 剑指 Offer 10-I. 斐波那契数列 # 题目 # 写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下:\nF(0) = 0, F(1) = 1 F(N) = F(N - 1) + F(N - 2), 其中 N \u0026gt; 1. 斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。\n思路 # 迭代 # 代码 # 迭代 # class Solution { public int fib(int n) { if (n == 0) return 0; if (n == 1) return 1; int one = 0, two = 1; for (int i = 2; i \u0026lt;= n; i++) { int temp = one % 1000000007 + two % 1000000007; one = two; two = temp; } return two % 1000000007; } } "},{"id":298,"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":299,"href":"/docs/codes/%E5%89%91%E6%8C%87-Offer/27.-%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E9%95%9C%E5%83%8F/","title":"27. 二叉树的镜像","section":"剑指 Offer","content":" 剑指 Offer 27. 二叉树的镜像 # 题目 # 给定一棵二叉树,输出其镜像。\n思路 # 代码 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { this.val = x; } } class Solution { public TreeNode mirrorTree(TreeNode root) { if (root == null || (root.left == null \u0026amp;\u0026amp; root.right == null)) return root; TreeNode temp = mirrorTree(root.left); root.left = mirrorTree(root.right); root.right = temp; return root; } } "},{"id":300,"href":"/docs/codes/%E5%89%91%E6%8C%87-Offer/28.-%E5%AF%B9%E7%A7%B0%E7%9A%84%E4%BA%8C%E5%8F%89%E6%A0%91/","title":"28. 对称的二叉树","section":"剑指 Offer","content":" 剑指 Offer 22. 对称的二叉树 # 题目 # 请实现一个函数,用来判断一棵二叉树是否是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。\n思路 # 代码 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { this.val = x; } } class Solution { public boolean isTwoSymmetric(TreeNode root1, TreeNode root2) { if (root1 == null) return root2 == null; if (root2 == null) return false; return (root1.val == root2.val) \u0026amp; isTwoSymmetric(root1.left, root2.right) \u0026amp; isTwoSymmetric(root1.right, root2.left); } public boolean isSymmetric(TreeNode root) { if (root == null) return true; return isTwoSymmetric(root.left, root.right); } } "},{"id":301,"href":"/docs/codes/%E5%89%91%E6%8C%87-Offer/32.-%E4%BB%8E%E4%B8%8A%E5%88%B0%E4%B8%8B%E6%89%93%E5%8D%B0%E4%BA%8C%E5%8F%89%E6%A0%91/","title":"32. 从上到下打印二叉树","section":"剑指 Offer","content":" 剑指 Offer 32. 从上到下打印二叉树 # 题目 # 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。 思路 # 层序遍历 # 代码 # 层序遍历 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } } class Solution { public int[] levelOrder(TreeNode root) { List\u0026lt;Integer\u0026gt; ans = new ArrayList\u0026lt;\u0026gt;(); Queue\u0026lt;TreeNode\u0026gt; queue = new LinkedList\u0026lt;\u0026gt;(); if (root != null) queue.offer(root); while (queue.size() != 0) { int layerSize = queue.size(); for (int i = 0; i \u0026lt; layerSize; i++) { TreeNode node = queue.poll(); ans.add(node.val); if (node.left != null) queue.offer(node.left); if (node.right != null) queue.offer(node.right); } } int[] result = new int[ans.size()]; for (int i = 0; i \u0026lt; ans.size(); i++) result[i] = ans.get(i); return result; } } DFS # "},{"id":302,"href":"/docs/codes/%E5%89%91%E6%8C%87-Offer/55.-%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%B7%B1%E5%BA%A6/","title":"55. 二叉树的深度","section":"剑指 Offer","content":" 剑指 Offer 55. 二叉树的深度 # 题目 # 给定一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。\n思路 # 代码 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { this.val = x; } } class Solution { public int maxDepth(TreeNode root) { if (root == null) return 0; return 1 + Math.max(maxDepth(root.left), maxDepth(root.right)); } } "},{"id":303,"href":"/docs/codes/%E9%9D%A2%E8%AF%95%E9%A2%98/%E9%9D%A2%E8%AF%95%E9%A2%98-01.01.-%E5%88%A4%E6%96%AD%E5%AD%97%E7%AC%A6%E6%98%AF%E5%90%A6%E5%94%AF%E4%B8%80/","title":"面试题 01.01. 判断字符是否唯一","section":"面试题","content":" 面试题 01.01. 判断字符是否唯一 # 题目 # 实现算法判断给定字符串 s 的所有字符是否全都不同。\ns[i] 仅包含小写字母。\n如果不使用额外的数据结构,会很加分。\n思路 # 哈希 位运算 代码 # 哈希 # class Solution { public boolean isUnique(String astr) { int[] record = new int[26]; for (int i = 0; i \u0026lt; astr.length(); i++) if (++record[astr.charAt(i) - \u0026#39;a\u0026#39;] == 2) return false; return true; } } 致谢 # 珍珠好好吃\nMAllk33\n"},{"id":304,"href":"/docs/codes/%E9%9D%A2%E8%AF%95%E9%A2%98/%E9%9D%A2%E8%AF%95%E9%A2%98-01.02.-%E5%88%A4%E5%AE%9A%E6%98%AF%E5%90%A6%E4%BA%92%E4%B8%BA%E5%AD%97%E7%AC%A6%E9%87%8D%E6%8E%92/","title":"面试题 01.02. 判定是否互为字符重排","section":"面试题","content":" 面试题 01.02. 判定是否互为字符重排 # 题目 # 给定两个由小写字母组成的字符串s1和s2。 判断其中一个字符串的字符经重排后能否变成另一个字符串。 思路 # 哈希 # 代码 # 哈希 # class Solution { public boolean CheckPermutation(String s1, String s2) { if (s1.length() != s2.length()) return false; char[] charArray1 = new char[26], charArray2 = new char[26]; for (int i = 0; i \u0026lt; s1.length(); i++) { charArray1[s1.charAt(i) - \u0026#39;a\u0026#39;] += 1; charArray2[s2.charAt(i) - \u0026#39;a\u0026#39;] += 1; } for (int i = 0; i \u0026lt; charArray1.length; i++) { if (charArray1[i] != charArray2[i]) return false; } return true; } } 致谢 # 宫水三叶\n"},{"id":305,"href":"/docs/codes/%E9%9D%A2%E8%AF%95%E9%A2%98/%E9%9D%A2%E8%AF%95%E9%A2%98-01.04.-%E5%9B%9E%E6%96%87%E6%8E%92%E5%88%97/","title":"面试题 01.04. 回文排列","section":"面试题","content":" 面试题 01.04. 回文排列 # 题目 # 给定一个字符串,编写一个函数判定其是否为某个回文串的排列之一。\n回文串是指正反两个方向都一样的单词或短语。排列是指字母的重新排列。\n回文串不一定是字典中的单词。\n思路 # 若 s.length() 为奇数,只允许存在一个元素仅出现一次。 若 s.length() 为偶数,不允许出现存在次数为偶数的元素。 代码 # class Solution { public boolean canPermutePalindrome(String s) { Map\u0026lt;Character, Integer\u0026gt; map = new HashMap\u0026lt;\u0026gt;(); for (int i = 0; i \u0026lt; s.length(); i++) map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1); int numOdd = 0; for (Integer cnt: map.values()) if (cnt % 2 == 1) numOdd += 1; return s.length() % 2 == 0 ? numOdd = 0 : numOdd == 1; } } "},{"id":306,"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":307,"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":308,"href":"/docs/codes/%E9%9D%A2%E8%AF%95%E9%A2%98/%E9%9D%A2%E8%AF%95%E9%A2%98-03.04.-%E5%8C%96%E6%A0%88%E4%B8%BA%E9%98%9F/","title":"面试题 03.04. 化栈为队","section":"面试题","content":" 面试题 03.04. 化栈为队 # 题目 # 实现一个 MyQueue 类,该类用两个栈实现一个队列。 思路 # 代码 # class MyQueue { Stack\u0026lt;Integer\u0026gt; inStack, outStack; /** Initialize your data structure here. */ public MyQueue() { this.inStack = new Stack\u0026lt;\u0026gt;(); this.outStack = new Stack\u0026lt;\u0026gt;(); } /** Push element x to the back of queue. */ public void push(int x) { this.inStack.push(x); } /** Removes the element from in front of queue and returns that element. */ public int pop() { if (this.outStack.size() == 0) { while (this.inStack.size() != 0) { this.outStack.push(this.inStack.pop()); } } return this.outStack.pop(); } /** Get the front element. */ public int peek() { if (this.outStack.size() == 0) { while (this.inStack.size() != 0) { this.outStack.push(this.inStack.pop()); } } return this.outStack.peek(); } /** Returns whether the queue is empty. */ public boolean empty() { return this.inStack.size() == 0 \u0026amp;\u0026amp; this.outStack.size() == 0; } } /** * Your MyQueue object will be instantiated and called as such: * MyQueue obj = new MyQueue(); * obj.push(x); * int param_2 = obj.pop(); * int param_3 = obj.peek(); * boolean param_4 = obj.empty(); */ "},{"id":309,"href":"/docs/codes/%E9%9D%A2%E8%AF%95%E9%A2%98/%E9%9D%A2%E8%AF%95%E9%A2%98-04.03.-%E7%89%B9%E5%AE%9A%E6%B7%B1%E5%BA%A6%E8%8A%82%E7%82%B9%E9%93%BE%E8%A1%A8/","title":"面试题 04.03. 特定深度节点链表","section":"面试题","content":" 面试题 04.03. 特定深度节点链表 # 题目 # 给定一棵二叉树,设计一个算法,创建含有某一深度上所有节点的链表。\n返回一个包含所有深度的链表的数组。\n思路 # 层序遍历变体 代码 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } } public class ListNode { int val; ListNode next; ListNode(int x) { val = x; } } class Solution { public ListNode[] listOfDepth(TreeNode tree) { /* 用queue存储单链表头节点,而后将queue转为ListNode[] */ Queue\u0026lt;ListNode\u0026gt; ansQueue = new LinkedList\u0026lt;\u0026gt;(); /* 二叉树的层序遍历 */ Queue\u0026lt;TreeNode\u0026gt; queue = new LinkedList\u0026lt;\u0026gt;(); queue.offer(tree); while (queue.size() != 0) { int layerSize = queue.size(); ListNode sentinel = new ListNode(-1), ptr = sentinel; for (int i = 0; i \u0026lt; layerSize; i++) { TreeNode node = queue.poll(); if (node.left != null) queue.offer(node.left); if (node.right != null) queue.offer(node.right); ptr = ptr.next = new ListNode(node.val); } ansQueue.offer(sentinel.next); } ListNode[] ans = new ListNode[ansQueue.size()]; /** 这里如果用 ans[i] = ansQueue.poll(); 则无法通过力扣 ???*/ int i = 0; for (ListNode node: ansQueue) ans[i++] = node; return ans; } } "},{"id":310,"href":"/docs/codes/%E9%9D%A2%E8%AF%95%E9%A2%98/%E9%9D%A2%E8%AF%95%E9%A2%98-04.04.-%E6%A3%80%E6%9F%A5%E5%B9%B3%E8%A1%A1%E6%80%A7/","title":"面试题 04.04. 检查平衡性","section":"面试题","content":" 面试题 04.04. 检查平衡性 # 题目 # 检查二叉树是否平衡 平衡二叉树的定义为: 任取一个节点,其两棵子树的高度差不超过 1 思路 # 递归 # 代码 # 递归 # public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { this.val = x; } } class Solution { public int depth(TreeNode root) { if (root == null) return 0; int leftDepth = depth(root.left); if (leftDepth == -1) return -1; int rightDepth = depth(root.right); if (rightDepth == -1) return -1; if (Math.abs(leftDepth - rightDepth) \u0026gt; 1) return -1; return 1 + Math.max(leftDepth, rightDepth); } public boolean isBalanced(TreeNode root) { return depth(root) == -1 ? false: true; } } "},{"id":311,"href":"/docs/codes/%E9%9D%A2%E8%AF%95%E9%A2%98/%E9%9D%A2%E8%AF%95%E9%A2%98-05.07.-%E9%85%8D%E5%AF%B9%E4%BA%A4%E6%8D%A2/","title":"面试题 05.07. 配对交换","section":"面试题","content":" 面试题 05.07. 配对交换 # 题目 # 配对交换,编写代码,交换某个整数的奇数位和偶数位,尽量使用较少的指令。\n即将位0与位1交换,位2与位3交换,以此类推。\n思路 # 位运算 代码 # local picture # class Solution { public int exchangeBits(int num) { int odd = 1 \u0026lt;\u0026lt; 1, even = 1 \u0026lt;\u0026lt; 0; while (0 \u0026lt;= odd \u0026amp;\u0026amp; odd \u0026lt;= (1 \u0026lt;\u0026lt; 29)) { if (((num \u0026amp; odd) != 0) \u0026amp;\u0026amp; (num \u0026amp; even) == 0) || (num \u0026amp; odd) == 0 \u0026amp;\u0026amp; (num \u0026amp; even) != 0) { num ^= odd ^ even; } odd \u0026lt;= 2; even \u0026lt;= 2; } return num; } } global picture # class Solution { public int exchangeBits(int num) { return ((num \u0026amp; 0xaaaaaaaa) \u0026gt;\u0026gt; 1) | ((num \u0026amp; 0x55555555) \u0026lt;\u0026lt; 1); } } 致谢 # 我要出去乱说\n"},{"id":312,"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)); "}]