Flutter Navigator 2(1),一个Android程序员的面试心得

这篇具有很好参考价值的文章主要介绍了Flutter Navigator 2(1),一个Android程序员的面试心得。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

onPressed: () {

Navigator.pushNamed(

context,

‘/details/1’,

);

},

),

),

);

}

}

class DetailScreen extends StatelessWidget {

String id;

DetailScreen({

this.id,

});

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(),

body: Center(

child: Column(

mainAxisAlignment: MainAxisAlignment.center,

children: [

Text(‘Viewing details for item $id’),

FlatButton(

child: Text(‘Pop!’),

onPressed: () {

Navigator.pop(context);

},

),

],

),

),

);

}

}

class UnknownScreen extends StatelessWidget {

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(),

body: Center(

child: Text(‘404!’),

),

);

}

}

这里,我们可以通过 RouteSettings 类型的对象 settings 可以拿到 Navigator.pushNamed 调用时传入的参数。

Navigator 2.0

Navigator 2.0 提供了一系列全新的接口,可以实现将路由状态成为应用状态的一部分,并能够通过底层 API 实现参数解析的功能,新增的 API 如下:

  • Page,用来表示 Navigator 路由栈中各个页面的配置信息。

  • Router,用来制定要由 Navigator 展示的页面列表,通常,该页面列表会根据系统或应用程序的状态改变而改变。

  • RouteInformationParser,持有 RouteInformationProvider 提供的 RouteInformation ,可以将其解析为我们定义的数据类型。

  • RouterDelegate,定义应用程序中的路由行为,例如 Router 如何知道应用程序状态的变化以及如何响应。主要的工作就是监听 RouteInformationParser 和应用状态并通过当前页面列表构建 ·。

  • BackButtonDispatcher,响应后退按钮,并通知 Router

下图展示了 RouterDelegateRouterRouteInformationParser 以及用用状态的交互原理,

Flutter Navigator 2(1),一个Android程序员的面试心得,程序员,flutter,android,javascript

大致流程如下:

  1. 当系统打开新页面(如 “books / 2”)时,RouteInformationParser 会将其转换为应用中的具体数据类型 T(如 BooksRoutePath)。

  2. 该数据类型会被传递给 RouterDelegatesetNewRoutePath 方法,我们可以在这里更新路由状态(如通过设置 selectedBookId)并调用 notifyListeners 响应该操作。

  3. notifyListeners 会通知 Router 重建 RouterDelegate(通过 build() 方法).

  4. RouterDelegate.build() 返回一个新的 Navigator 实例,并最终展示出我们想要打开的页面(如 selectedBookId)。

Navigator 2.0 实战

下面,我们就来使用 Navigator 2.0 做一个小小练习,我们将实现一个 Flutter 应用,该应用作用在 Web 上时路由状态会与浏览器中的 URL 连接保持一致,而且也能够处理浏览器的回退按钮,如下:

Flutter Navigator 2(1),一个Android程序员的面试心得,程序员,flutter,android,javascript

接下来,使用 flutter channel master 将 Flutter 切换到 master 版本,创建一个支持 Web 应用的 Flutter 项目,lib/main.dart 中的代码如下:

import ‘package:flutter/material.dart’;

void main() {

runApp(BooksApp());

}

class Book {

final String title;

final String author;

Book(this.title, this.author);

}

class BooksApp extends StatefulWidget {

@override

State createState() => _BooksAppState();

}

class _BooksAppState extends State {

void initState() {

super.initState();

}

@override

Widget build(BuildContext context) {

return MaterialApp(

title: ‘Books App’,

home: Navigator(

pages: [

MaterialPage(

key: ValueKey(‘BooksListPage’),

child: Scaffold(),

)

],

onPopPage: (route, result) => route.didPop(result),

),

);

}

}

Pages

Navigator 接受一个 pages 参数,如果 Page 列表发生变化,Navigator 也需要更新当前路由栈来保持同步,下面我们就来使用该性质,在新建的项目中开发一个可以展示书单列表的应用

_BooksAppState 中持有两个状态参数:书单列表和当前所选书籍:

class _BooksAppState extends State {

// New:

Book _selectedBook;

bool show404 = false;

List books = [

Book(‘Stranger in a Strange Land’, ‘Robert A. Heinlein’),

Book(‘Foundation’, ‘Isaac Asimov’),

Book(‘Fahrenheit 451’, ‘Ray Bradbury’),

];

// …

然后,在中_BooksAppState,返回一个带有 Page 对象列表的 Navigator :

@override

Widget build(BuildContext context) {

return MaterialApp(

title: ‘Books App’,

home: Navigator(

pages: [

MaterialPage(

key: ValueKey(‘BooksListPage’),

child: BooksListScreen(

books: books,

onTapped: _handleBookTapped,

),

),

],

),

);

}

void _handleBookTapped(Book book) {

setState(() {

_selectedBook = book;

});

}

// …

class BooksListScreen extends StatelessWidget {

final List books;

final ValueChanged onTapped;

BooksListScreen({

@required this.books,

@required this.onTapped,

});

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(),

body: ListView(

children: [

for (var book in books)

ListTile(

title: Text(book.title),

subtitle: Text(book.author),

onTap: () => onTapped(book),

)

],

),

);

}

}

由于此应用会有两个页面(一个书单列表也和一个详情的页面),如果选择了某本书(使用 collection if),则会加入详细页:

pages: [

MaterialPage(

key: ValueKey(‘BooksListPage’),

child: BooksListScreen(

books: books,

onTapped: _handleBookTapped,

),

),

// New:

if (show404)

MaterialPage(key: ValueKey(‘UnknownPage’), child: UnknownScreen())

else if (_selectedBook != null)

MaterialPage(

key: ValueKey(_selectedBook),

child: BookDetailsScreen(book: _selectedBook))

],

注意,这里的 key 会由 book 对象中的值定义作为 MaterialPage 的唯一标识,也就是说,book 对象不同这里的 MaterialPage 就不同。没有唯一的 key,框架就无法确定何时显示不同 Page 之间的过渡动画。

我们还可以继承 Page 来实现自定义行为,例如,在该页面添加了自定义过渡动画:

class BookDetailsPage extends Page {

final Book book;

BookDetailsPage({

this.book,

}) : super(key: ValueKey(book));

Route createRoute(BuildContext context) {

return PageRouteBuilder(

settings: this,

pageBuilder: (context, animation, animation2) {

final tween = Tween(begin: Offset(0.0, 1.0), end: Offset.zero);

final curveTween = CurveTween(curve: Curves.easeInOut);

return SlideTransition(

position: animation.drive(curveTween).drive(tween),

child: BookDetailsScreen(

key: ValueKey(book),

book: book,

),

);

},

);

}

}

还需要注意的是,只传入 pages 参数而不传入 onPopPage 也会报错,他接受一个回调函数,每次 Navigator.pop() 被调用时就会出发这个函数,我们可以在其中更新路由状态

最后,在pages不提供onPopPage回调的情况下提供参数是错误的。每次调用时都会Navigator.pop()调用此函数。应该使用它来更新状态(修改页面列表),这里我们需要调用 didPop 方法确定是否 pop 成功:

onPopPage: (route, result) {

if (!route.didPop(result)) {

return false;

}

// Update the list of pages by setting _selectedBook to null

setState(() {

_selectedBook = null;

});

return true;

},

我们还必须在更新应用程序状态之前检查是否 pop 失败。这里,我们使用了 setState 方法来通知 Flutter 调用 build() 方法,该方法 _selectedBook 为 null 表示展示书单列表页。

完整代码如下:

import ‘package:flutter/material.dart’;

void main() {

runApp(BooksApp());

}

class Book {

final String title;

final String author;

Book(this.title, this.author);

}

class BooksApp extends StatefulWidget {

@override

State createState() => _BooksAppState();

}

class _BooksAppState extends State {

Book _selectedBook;

List books = [

Book(‘Stranger in a Strange Land’, ‘Robert A. Heinlein’),

Book(‘Foundation’, ‘Isaac Asimov’),

Book(‘Fahrenheit 451’, ‘Ray Bradbury’),

];

@override

Widget build(BuildContext context) {

return MaterialApp(

title: ‘Books App’,

home: Navigator(

pages: [

MaterialPage(

key: ValueKey(‘BooksListPage’),

child: BooksListScreen(

books: books,

onTapped: _handleBookTapped,

),

),

if (_selectedBook != null) BookDetailsPage(book: _selectedBook)

],

onPopPage: (route, result) {

if (!route.didPop(result)) {

return false;

}

// Update the list of pages by setting _selectedBook to null

setState(() {

_selectedBook = null;

});

return true;

},

),

);

}

void _handleBookTapped(Book book) {

setState(() {

_selectedBook = book;

});

}

}

class BookDetailsPage extends Page {

final Book book;

BookDetailsPage({

this.book,

}) : super(key: ValueKey(book));

Route createRoute(BuildContext context) {

return MaterialPageRoute(

settings: this,

builder: (BuildContext context) {

return BookDetailsScreen(book: book);

},

);

}

}

class BooksListScreen extends StatelessWidget {

final List books;

final ValueChanged onTapped;

BooksListScreen({

@required this.books,

@required this.onTapped,

});

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(),

body: ListView(

children: [

for (var book in books)

ListTile(

title: Text(book.title),

subtitle: Text(book.author),

onTap: () => onTapped(book),

)

],

),

);

}

}

class BookDetailsScreen extends StatelessWidget {

final Book book;

BookDetailsScreen({

@required this.book,

});

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(),

body: Padding(

padding: const EdgeInsets.all(8.0),

child: Column(

crossAxisAlignment: CrossAxisAlignment.start,

children: [

if (book != null) …[

Text(book.title, style: Theme.of(context).textTheme.headline6),

Text(book.author, style: Theme.of(context).textTheme.subtitle1),

],

],

),

),

);

}

}

目前,我们就实现了声明式的路由管理,单此时我们还无法处理浏览器的后退按钮,也不能同步浏览器地址拦中的链接。

Router

本节,我们来实现通过 RouteInformationParser, RouterDelegate 更新路由状态,实现与浏览器地址拦中的链接同步

数据类型

首先,我们需要通过 RouteInformationParser 将路由信息解析为指定的数据类型:

class BookRoutePath {

final int id;

final bool isUnknown;

BookRoutePath.home()
id = null,

isUnknown = false;

BookRoutePath.details(this.id) : isUnknown = false;

BookRoutePath.unknown()
id = null,

isUnknown = true;

bool get isHomePage => id == null;

bool get isDetailsPage => id != null;

}

在该应用程序中,可以使用 BookRoutePath 类来表示应用程序中的路由路径,我们也可以实现父子类来关系其他各类型的路由信息。

RouterDelegate

接下来,我们实现一个 RouterDelegate 的子类 BookRouterDelegate

class BookRouterDelegate extends RouterDelegate

with ChangeNotifier, PopNavigatorRouterDelegateMixin {

@override

Widget build(BuildContext context) {

// TODO

throw UnimplementedError();

}

@override

// TODO

GlobalKey get navigatorKey => throw UnimplementedError();

@override

Future setNewRoutePath(BookRoutePath configuration) {

// TODO

throw UnimplementedError();

}

}

BookRouterDelegate 的泛型为 BookRoutePath,其中包含了决定显示哪个页面所需的所有状态。

此时,我们就可以将 _BooksAppState 中的路由相关的逻辑放到 BookRouterDelegate 中,这里,我们创建了一个 GlobalKey 对象,其他各个状态也都保存在这里面:

class BookRouterDelegate extends RouterDelegate

with ChangeNotifier, PopNavigatorRouterDelegateMixin {

final GlobalKey navigatorKey;

Book _selectedBook;

bool show404 = false;

List books = [

Book(‘Stranger in a Strange Land’, ‘Robert A. Heinlein’),

Book(‘Foundation’, ‘Isaac Asimov’),

Book(‘Fahrenheit 451’, ‘Ray Bradbury’),

];

BookRouterDelegate() : navigatorKey = GlobalKey();

// …

为了能在 URL 中显示正确的路径,我们也需要根据应用程序的当前状态返回一个 BookRoutePath 对象:

BookRoutePath get currentConfiguration {

if (show404) {

return BookRoutePath.unknown();

}

return _selectedBook == null

? BookRoutePath.home()
BookRoutePath.details(books.indexOf(_selectedBook));

}

下面,build 方法返回一个 Navigator 组件:

@override

Widget build(BuildContext context) {

return Navigator(

key: navigatorKey,

pages: [

MaterialPage(

key: ValueKey(‘BooksListPage’),

child: BooksListScreen(

books: books,

onTapped: _handleBookTapped,

),

),

if (show404)

MaterialPage(key: ValueKey(‘UnknownPage’), child: UnknownScreen())

else if (_selectedBook != null)

BookDetailsPage(book: _selectedBook)

],

onPopPage: (route, result) {

if (!route.didPop(result)) {

return false;

}

// Update the list of pages by setting _selectedBook to null

_selectedBook = null;

show404 = false;

notifyListeners();

return true;

},

);

}

因为该类并不是组件,而是由 ChangeNotifier 实现,因此这里的 onPopPage 方法需要使用 notifyListeners 替代 setState 来改变状态,当 RouterDelegate 触发状态更新时,Router 同样会触发 RouterDelegatecurrentConfiguration 方法并调用 build 方法创建出一个新的 Navigator 组件。

_handleBookTapped方法也需要使用 notifyListeners 代替 setState

void _handleBookTapped(Book book) {

_selectedBook = book;

notifyListeners();

}

新页面打开后,Router 会调用setNewRoutePath 方法来更新应用程序的路由状态:

@override

Future setNewRoutePath(BookRoutePath path) async {

if (path.isUnknown) {

_selectedBook = null;

show404 = true;

return;

}

if (path.isDetailsPage) {

if (path.id < 0 || path.id > books.length - 1) {

show404 = true;

return;

}

_selectedBook = books[path.id];

} else {

_selectedBook = null;

}

show404 = false;

}

RouteInformationParser

RouteInformationParser 内部含有一个钩子函数,接受路由信息(RouteInformation),我们可以在这里将它转换成指定的数据类型(BookRoutePath)并使用 Uri 解析:

class BookRouteInformationParser extends RouteInformationParser {

@override

Future parseRouteInformation(

RouteInformation routeInformation) async {

final uri = Uri.parse(routeInformation.location);

// Handle ‘/’

if (uri.pathSegments.length == 0) {

return BookRoutePath.home();

}

// Handle ‘/book/:id’

if (uri.pathSegments.length == 2) {

if (uri.pathSegments[0] != ‘book’) return BookRoutePath.unknown();

var remaining = uri.pathSegments[1];

var id = int.tryParse(remaining);

if (id == null) return BookRoutePath.unknown();

return BookRoutePath.details(id);

}

// Handle unknown routes

return BookRoutePath.unknown();

}

@override

RouteInformation restoreRouteInformation(BookRoutePath path) {

if (path.isUnknown) {

return RouteInformation(location: ‘/404’);

}

if (path.isHomePage) {

return RouteInformation(location: ‘/’);

}

if (path.isDetailsPage) {

return RouteInformation(location: ‘/book/${path.id}’);

}

return null;

}

}

该实现仅针对此应用,并不是常规的路由解析解决方案,具体原理,我们以后再详细了解。最后,要使用这些定义好的类,我们还需要使用全新的 MaterialApp.router 构造函数并传入它们各自的实现:

return MaterialApp.router(

title: ‘Books App’,

routerDelegate: _routerDelegate,

routeInformationParser: _routeInformationParser,

);

完整代码如下:

import ‘package:flutter/material.dart’;

void main() {

runApp(BooksApp());

}

class Book {

final String title;

final String author;

Book(this.title, this.author);

}

class BooksApp extends StatefulWidget {

@override

State createState() => _BooksAppState();

}

class _BooksAppState extends State {

BookRouterDelegate _routerDelegate = BookRouterDelegate();

BookRouteInformationParser _routeInformationParser =

BookRouteInformationParser();

@override

Widget build(BuildContext context) {

return MaterialApp.router(

title: ‘Books App’,

routerDelegate: _routerDelegate,

routeInformationParser: _routeInformationParser,

);

}

}

class BookRouteInformationParser extends RouteInformationParser {

@override

Future parseRouteInformation(

RouteInformation routeInformation) async {

final uri = Uri.parse(routeInformation.location);

// Handle ‘/’

if (uri.pathSegments.length == 0) {

return BookRoutePath.home();

}

// Handle ‘/book/:id’

if (uri.pathSegments.length == 2) {

if (uri.pathSegments[0] != ‘book’) return BookRoutePath.unknown();

var remaining = uri.pathSegments[1];

var id = int.tryParse(remaining);

if (id == null) return BookRoutePath.unknown();

return BookRoutePath.details(id);

}

// Handle unknown routes

return BookRoutePath.unknown();

}

@override

RouteInformation restoreRouteInformation(BookRoutePath path) {

if (path.isUnknown) {

return RouteInformation(location: ‘/404’);

}

if (path.isHomePage) {

return RouteInformation(location: ‘/’);

}

if (path.isDetailsPage) {

return RouteInformation(location: ‘/book/${path.id}’);

}

return null;

}

}

class BookRouterDelegate extends RouterDelegate

with ChangeNotifier, PopNavigatorRouterDelegateMixin {

final GlobalKey navigatorKey;

Book _selectedBook;

bool show404 = false;

List books = [

Book(‘Stranger in a Strange Land’, ‘Robert A. Heinlein’),

Book(‘Foundation’, ‘Isaac Asimov’),

Book(‘Fahrenheit 451’, ‘Ray Bradbury’),

];

BookRouterDelegate() : navigatorKey = GlobalKey();

BookRoutePath get currentConfiguration {

if (show404) {

return BookRoutePath.unknown();

}

return _selectedBook == null

? BookRoutePath.home()
BookRoutePath.details(books.indexOf(_selectedBook));

}

@override

Widget build(BuildContext context) {

return Navigator(

key: navigatorKey,

pages: [

MaterialPage(

key: ValueKey(‘BooksListPage’),

child: BooksListScreen(

books: books,

onTapped: _handleBookTapped,

),

),

if (show404)

MaterialPage(key: ValueKey(‘UnknownPage’), child: UnknownScreen())

else if (_selectedBook != null)

BookDetailsPage(book: _selectedBook)

],

onPopPage: (route, result) {

if (!route.didPop(result)) {

return false;

}

// Update the list of pages by setting _selectedBook to null

_selectedBook = null;

show404 = false;

notifyListeners();

return true;

},

);

}

@override

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

Flutter Navigator 2(1),一个Android程序员的面试心得,程序员,flutter,android,javascript

Flutter Navigator 2(1),一个Android程序员的面试心得,程序员,flutter,android,javascript

Flutter Navigator 2(1),一个Android程序员的面试心得,程序员,flutter,android,javascript

Flutter Navigator 2(1),一个Android程序员的面试心得,程序员,flutter,android,javascript

Flutter Navigator 2(1),一个Android程序员的面试心得,程序员,flutter,android,javascript

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

Flutter Navigator 2(1),一个Android程序员的面试心得,程序员,flutter,android,javascript

推荐学习资料


  • 脑图
    Flutter Navigator 2(1),一个Android程序员的面试心得,程序员,flutter,android,javascript
    Flutter Navigator 2(1),一个Android程序员的面试心得,程序员,flutter,android,javascript
    Flutter Navigator 2(1),一个Android程序员的面试心得,程序员,flutter,android,javascript

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!文章来源地址https://www.toymoban.com/news/detail-848518.html

[

MaterialPage(

key: ValueKey(‘BooksListPage’),

child: BooksListScreen(

books: books,

onTapped: _handleBookTapped,

),

),

if (show404)

MaterialPage(key: ValueKey(‘UnknownPage’), child: UnknownScreen())

else if (_selectedBook != null)

BookDetailsPage(book: _selectedBook)

],

onPopPage: (route, result) {

if (!route.didPop(result)) {

return false;

}

// Update the list of pages by setting _selectedBook to null

_selectedBook = null;

show404 = false;

notifyListeners();

return true;

},

);

}

@override

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-9PMPoVOL-1712507128125)]

[外链图片转存中…(img-AeGeEdAb-1712507128125)]

[外链图片转存中…(img-TrXmGqgo-1712507128126)]

[外链图片转存中…(img-vzOtxhmP-1712507128126)]

[外链图片转存中…(img-2tXefhBn-1712507128126)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

Flutter Navigator 2(1),一个Android程序员的面试心得,程序员,flutter,android,javascript

推荐学习资料


  • 脑图
    [外链图片转存中…(img-X0wQZVPj-1712507128126)]
    [外链图片转存中…(img-If4CUb2J-1712507128127)]
    [外链图片转存中…(img-lpVT5oDz-1712507128127)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

到了这里,关于Flutter Navigator 2(1),一个Android程序员的面试心得的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【程序员面试金典】面试题 17.13. 恢复空格

    描述:哦,不!你不小心把一个长篇文章中的空格、标点都删掉了,并且大写也弄成了小写。像句子\\\"I reset the computer. It still didn’t boot!“已经变成了\\\"iresetthecomputeritstilldidntboot”。在处理标点符号和大小写之前,你得先把它断成词语。当然了,你有一本厚厚的词典dictionary,不

    2024年02月11日
    浏览(48)
  • 程序员必备的面试技巧

    “程序员必备的面试技巧,就像是编写一段完美的代码一样重要。在面试战场上,我们需要像忍者一样灵活,像侦探一样聪明,还要像无敌铁金刚一样坚定。只有掌握了这些技巧,我们才能在面试的舞台上闪耀光芒,成为那个令HR们心动的程序猿!” 提醒:在发布作品前,请

    2024年01月21日
    浏览(51)
  • 程序员面试完之后,人麻了...

    去面试吧   面不被录用的试 面hr为了完成任务的试 面一轮二轮没有下文试 面需要通勤2小时的试 面随时加班的试 ...... 今年的“金三银四”被网友们称为“铜三铁四”, 招聘软件上的岗位都能背下来了,简历却依然石沉大海。 好不容易等来个回复,还不如不回复 或者是遇到

    2023年04月23日
    浏览(39)
  • 【程序员面试金典】面试题 17.25 . 单词矩阵

    描述:给定一份单词的清单,设计一个算法,创建由字母组成的面积最大的矩形,其中每一行组成一个单词(自左向右),每一列也组成一个单词(自上而下)。不要求这些单词在清单里连续出现,但要求所有行等长,所有列等高。 如果有多个面积最大的矩形,输出任意一个均可

    2024年02月12日
    浏览(43)
  • 【程序员面试金典】面试题 17.22 . 单词转换

    描述:给定字典中的两个词,长度相等。写一个方法,把一个词转换成另一个词, 但是一次只能改变一个字符。每一步得到的新词都必须能在字典中找到。 编写一个程序,返回一个可能的转换序列。如有多个可能的转换序列,你可以返回任何一个。 示例 1: 示例 2: 思路:最

    2024年02月11日
    浏览(40)
  • 【程序员面试金典】面试题 17.23. 最大黑方阵

    描述:给定一个方阵,其中每个单元(像素)非黑即白。设计一个算法,找出 4 条边皆为黑色像素的最大子方阵。 返回一个数组 [r, c, size] ,其中 r, c 分别代表子方阵左上角的行号和列号,size 是子方阵的边长。若有多个满足条件的子方阵,返回 r 最小的,若 r 相同,返回 c 最小

    2024年02月12日
    浏览(38)
  • 【程序员面试金典】面试题 17.26. 稀疏相似度

    描述:两个(具有不同单词的)文档的交集(intersection)中元素的个数除以并集(union)中元素的个数,就是这两个文档的相似度。例如,{1, 5, 3} 和 {1, 7, 2, 3} 的相似度是 0.4,其中,交集的元素有 2 个,并集的元素有 5 个。给定一系列的长篇文档,每个文档元素各不相同,并与一个

    2024年02月12日
    浏览(37)
  • 【程序员面试金典】面试题 17.14. 最小K个数

    描述:设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。 示例: 提示: 0 = len(arr) = 100000 0 = k = min(100000, len(arr)) 思路:最直观的想法是,排序。 扩展:最大堆。最小的k个数,那么就可以维持一个大小为k的最大堆,先填充k个数到最大堆中,然后再依次遍

    2024年02月11日
    浏览(55)
  • 【程序员面试金典】面试题 17.19. 消失的两个数字

    描述:给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗? 以任意顺序返回这两个数字均可。 示例 1: 示例 2: 提示: nums.length = 30000 思路:最直观的想法是,位运算。消失的两个数字和只出现一次的两个元素,本质

    2024年02月12日
    浏览(48)
  • 【程序员面试金典】面试题 17.21. 直方图的水量

    描述:给定一个直方图(也称柱状图),假设有人从上面源源不断地倒水,最后直方图能存多少水量?直方图的宽度为 1。 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的直方图,在这种情况下,可以接 6 个单位的水(蓝色部分表示水)。 感谢 Marcos 贡献此图。 示例: 思路:最直观的想

    2024年02月11日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包